الفرق بين المراجعتين ل"React/lists and keys"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
سطر 44: سطر 44:
 
   document.getElementById('root')
 
   document.getElementById('root')
 
);
 
);
</syntaxhighlight>
+
</syntaxhighlight>عندما تُنفَّذ هذه الشيفرة ستتلقى تحذيرًا أنّه يجب تزويد مفتاح (key) لعناصر القائمة. والمفتاح هو عبارة عن خاصيّة على شكل سلسلة نصيّة يجب إضافتها عند إنشاء قوائم من العناصر. سنناقش أهميته في الفقرة القادمة.
 +
 
 +
فلنُعيِّن مفتاح <code>key</code> لعناصر القائمة بداخل التابع <code>numbers.map()</code>‎ وبذلك نُصلِح مشكلة المفتاح المفقود:<syntaxhighlight lang="javascript">
 +
function NumberList(props) {
 +
  const numbers = props.numbers;
 +
  const listItems = numbers.map((number) =>
 +
    <li key={number.toString()}>
 +
      {number}
 +
    </li>
 +
  );
 +
  return (
 +
    <ul>{listItems}</ul>
 +
  );
 +
}
 +
 
 +
const numbers = [1, 2, 3, 4, 5];
 +
ReactDOM.render(
 +
  <NumberList numbers={numbers} />,
 +
  document.getElementById('root')
 +
);
 +
</syntaxhighlight>[https://codepen.io/gaearon/pen/jrXYRR?editors=0011 جرب المثال على موقع CodePen].
 +
 
 +
== المفاتيح (Keys) ==
 +
تُساعِد المفاتيح React على معرفة العناصر التي تغيرت، أو أُضيفت، أو أُزيلت. يجب أن تُعطَى المفاتيح للعناصر بداخل المصفوفة وذلك لإعطاء هذه العناصر هوية مستقرة:<syntaxhighlight lang="javascript">
 +
const numbers = [1, 2, 3, 4, 5];
 +
const listItems = numbers.map((number) =>
 +
  <li key={number.toString()}>
 +
    {number}
 +
  </li>
 +
);
 +
</syntaxhighlight>أفضل طريقة لانتقاء مفتاح هي استخدام سلسلة نصيّة تُعرِّف بشكل فريد عنصر القائمة عن العناصر الأخرى، نستخدم غالبًا المُعرِّفات (<code>IDs</code>) من بياناتنا كمفاتيح:<syntaxhighlight lang="javascript">
 +
const todoItems = todos.map((todo) =>
 +
  <li key={todo.id}>
 +
    {todo.text}
 +
  </li>
 +
);
 +
</syntaxhighlight>عندما لا تملك مُعرِّفات مستقرة للعناصر، فبإمكانك استخدام فهرس العنصر (<code>index</code>) كمفتاح كملاذ أخير:<syntaxhighlight lang="javascript">
 +
const todoItems = todos.map((todo, index) =>
 +
  // افعل ذلك فقط إن لم لكن للعناصر معرّفات مستقرة
 +
  <li key={index}>
 +
    {todo.text}
 +
  </li>
 +
);
 +
 
 +
</syntaxhighlight>لا نُفضِّل استخدام فهارس العناصر إن كان ترتيبها عُرضةً للتغيير، فقد يُؤثِّر هذا بشكل سلبي على الأداء وقد يسبب مشاكل مع حالة المُكوِّن. اطّلع على [https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318 هذا المقال للحصول على شرح مُفصّل للتأثيرات السلبية لاستخدام الفهرس كمفتاح]. إن اخترت عدم تعيين مفتاح لعناصر القائمة فستستخدم React الفهارس كمفاتيح بشكل افتراضي.
 +
 
 +
إن كنت ترغب بمعرفة المزيد ستجد هنا [https://reactjs.org/docs/reconciliation.html#recursing-on-children شرحا مفصلا حول أهمية المفاتيح].

مراجعة 11:24، 17 يوليو 2018

فلنتذكّر أولًا كيفيّة تحويل القوائم في JavaScript.

في المثال التالي سنستخدم الدالة  map()‎ لمضاعفة قيم مصفوفة من الأرقام اسمها numbers، وسنُعيِّن المصفوفة الجديدة التي تُعيدها الدالة map()‎ إلى المتغير doubled ثم نعرض محتواه عبر التابع console.log()‎:

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);
console.log(doubled);

نتيجة تنفيذ هذا المثال هي [2, 4, 6, 8, 10].

يكون تحويل المصفوفات في React إلى قوائم من العناصر مماثلًا تقريبا لذلك.

تصيير مكونات متعددة

بإمكانك بناء مجموعات من العناصر وتضمينها في JSX باستخدام الأقواس {}.

في المثال التالي سنستخدم الدالة map()‎ للمرور على جميع عناصر مصفوفة الأرقام numbers بحيث نُعيد عنصر <li> لكل عنصر من هذه المصفوفة. وأخيرا نُعيِّن مصفوفة العناصر الناتجة إلى المتغير listItems:

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li>{number}</li>
);

نضع الآن كامل المصفوفة listItems بداخل عنصر <ul>، ونُصيِّره إلى DOM:

ReactDOM.render(
  <ul>{listItems}</ul>,
  document.getElementById('root')
);

جرب المثال على موقع CodePen.

تعرض هذه الشيفرة قائمة منقطة مؤلفة من الأرقام بين 1 و 5.

مكون يحتوي على قائمة بسيطة

نُصيِّر عادةً القوائم بداخل المُكوِّنات، لذلك بإمكاننا إعادة كتابة المثال السابق باستخدام مُكوِّن يقبل مصفوفة من الأرقام تُدعى numbers ويعرض عناصرها على شكل قائمة غير مرتبة:

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <li>{number}</li>
  );
  return (
    <ul>{listItems}</ul>
  );
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

عندما تُنفَّذ هذه الشيفرة ستتلقى تحذيرًا أنّه يجب تزويد مفتاح (key) لعناصر القائمة. والمفتاح هو عبارة عن خاصيّة على شكل سلسلة نصيّة يجب إضافتها عند إنشاء قوائم من العناصر. سنناقش أهميته في الفقرة القادمة. فلنُعيِّن مفتاح key لعناصر القائمة بداخل التابع numbers.map()‎ وبذلك نُصلِح مشكلة المفتاح المفقود:

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <li key={number.toString()}>
      {number}
    </li>
  );
  return (
    <ul>{listItems}</ul>
  );
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

جرب المثال على موقع CodePen.

المفاتيح (Keys)

تُساعِد المفاتيح React على معرفة العناصر التي تغيرت، أو أُضيفت، أو أُزيلت. يجب أن تُعطَى المفاتيح للعناصر بداخل المصفوفة وذلك لإعطاء هذه العناصر هوية مستقرة:

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li key={number.toString()}>
    {number}
  </li>
);

أفضل طريقة لانتقاء مفتاح هي استخدام سلسلة نصيّة تُعرِّف بشكل فريد عنصر القائمة عن العناصر الأخرى، نستخدم غالبًا المُعرِّفات (IDs) من بياناتنا كمفاتيح:

const todoItems = todos.map((todo) =>
  <li key={todo.id}>
    {todo.text}
  </li>
);

عندما لا تملك مُعرِّفات مستقرة للعناصر، فبإمكانك استخدام فهرس العنصر (index) كمفتاح كملاذ أخير:

const todoItems = todos.map((todo, index) =>
  // افعل ذلك فقط إن لم لكن للعناصر معرّفات مستقرة
  <li key={index}>
    {todo.text}
  </li>
);

لا نُفضِّل استخدام فهارس العناصر إن كان ترتيبها عُرضةً للتغيير، فقد يُؤثِّر هذا بشكل سلبي على الأداء وقد يسبب مشاكل مع حالة المُكوِّن. اطّلع على هذا المقال للحصول على شرح مُفصّل للتأثيرات السلبية لاستخدام الفهرس كمفتاح. إن اخترت عدم تعيين مفتاح لعناصر القائمة فستستخدم React الفهارس كمفاتيح بشكل افتراضي.

إن كنت ترغب بمعرفة المزيد ستجد هنا شرحا مفصلا حول أهمية المفاتيح.