نمایش لیست‌ها در JSX و اهمیت Key

در بسیاری از برنامه‌ها، داده به‌شکل آرایه‌ای از موارد مشابه وجود دارد؛ مانند لیست محصولات، لیست کاربران یا لیست پیام‌ها. در این درس می‌بینیم چطور از این آرایه‌ها، لیستی از کامپوننت‌ها بسازیم و چرا React برای این کار به یک مقدار به نام Key نیاز دارد.

تبدیل آرایه به لیستی از JSX

چون JSX در نهایت جاوااسکریپت است، می‌توانیم از متد map روی آرایه‌ها برای تولید لیستی از عناصر JSX استفاده کنیم:

const fruits = ["سیب", "موز", "پرتقال"];

function FruitList() {
  return (
    <ul>
      {fruits.map((fruit) => (
        <li>{fruit}</li>
      ))}
    </ul>
  );
}

در این کد، به ازای هر عضو آرایه fruits، یک عنصر <li> ساخته می‌شود و نتیجه، آرایه‌ای از عناصر JSX است که React آن را داخل <ul> رندر می‌کند.

هشدار React درباره Key

اگر کد بالا را اجرا کنیم، در کنسول مرورگر هشداری می‌بینیم مبنی بر اینکه هر عنصر لیست باید یک key منحصربه‌فرد داشته باشد. برای رفع این هشدار، باید به هر عنصر یک ویژگی key بدهیم:

function FruitList() {
  return (
    <ul>
      {fruits.map((fruit, index) => (
        <li key={index}>{fruit}</li>
      ))}
    </ul>
  );
}

Key چیست و چرا React به آن نیاز دارد

Key یک مقدار منحصربه‌فرد است که به React کمک می‌کند هر عنصر لیست را در طول زمان، بین رندرهای مختلف، شناسایی کند. وقتی داده لیست تغییر می‌کند (مثلاً یک آیتم اضافه، حذف یا جابه‌جا می‌شود)، React از Key استفاده می‌کند تا بفهمد کدام آیتم همان آیتم قبلی است و کدام آیتم جدید است.

بدون Key، یا با Key نامناسب، React ممکن است اشتباهاً تصور کند یک آیتم تغییر کرده، در حالی که در واقع فقط جای آیتم‌ها عوض شده است. این موضوع می‌تواند باعث رفتارهای غیرمنتظره شود، به‌خصوص وقتی هر آیتم لیست، State داخلی خودش را داشته باشد. بررسی دقیق‌تر این رفتار را در فصل مربوط به «حفظ و بازنشانی State» خواهیم دید؛ در این درس فقط با نقش پایه‌ای Key آشنا می‌شویم.

چرا استفاده از index به‌عنوان Key توصیه نمی‌شود

در مثال بالا از index آرایه به‌عنوان Key استفاده کردیم؛ این کار در ساده‌ترین موارد کار می‌کند، اما یک مشکل دارد: اگر ترتیب آیتم‌ها تغییر کند، تعداد آیتم‌ها تغییر کند یا آیتمی از وسط لیست حذف شود، مقدار index مربوط به هر آیتم عوض می‌شود، حتی اگر خود آیتم همان آیتم قبلی باشد. این باعث می‌شود React نتواند به‌درستی تشخیص دهد کدام آیتم واقعاً همان قبلی است.

به همین دلیل، بهترین انتخاب برای Key، یک شناسه پایدار و منحصربه‌فرد است که به خود داده مرتبط است؛ مثلاً شناسه‌ای که از پایگاه داده می‌آید:

const products = [
  { id: "p1", name: "کیبورد" },
  { id: "p2", name: "ماوس" },
];

function ProductList() {
  return (
    <ul>
      {products.map((product) => (
        <li key={product.id}>{product.name}</li>
      ))}
    </ul>
  );
}

Key فقط در سطح والد بلافصل معنا دارد

Key فقط باید در میان عناصری که مستقیماً کنار هم و از یک آرایه ساخته می‌شوند، منحصربه‌فرد باشد؛ نیازی نیست Key در کل برنامه یکتا باشد. همچنین Key به‌عنوان یک Prop معمولی در اختیار خود کامپوننت قرار نمی‌گیرد؛ React آن را جدا و فقط برای مقاصد داخلی خودش استفاده می‌کند.

مثال قابل اجرا

رندر لیست با Key پایدار
برای دیدن پیش‌نمایش کامپوننت، روی Run بزنید.

جمع‌بندی

برای رندر یک لیست در JSX، معمولاً از متد map برای تبدیل آرایه داده به آرایه‌ای از عناصر JSX استفاده می‌کنیم. هر عنصر این لیست باید یک ویژگی key منحصربه‌فرد و در حالت ایده‌آل پایدار داشته باشد تا React بتواند آیتم‌ها را بین رندرهای مختلف به‌درستی شناسایی کند. استفاده از index به‌عنوان Key فقط باید در مواردی باشد که لیست هرگز جابه‌جا، اضافه یا کم نمی‌شود. با این درس، فصل اول را از نظر مفهومی به پایان می‌رسانیم و در ادامه به سراغ آزمون فصل ۱ می‌رویم.