هر چیزی که باید در مورد Key Prop ها در ریکت بدانید

در مورد Key Prop ها در ریکت

یک روش رایج جهت ایجاد زیر کامپوننت ها با استفاده از عناصر درون یک آرایه در جاوا اسکریپت یا ریکت استفاده از متد map مانند زیر است:

const List = () => {
    const listItems = ['Item 1', 'Item 2', 'Item 3'];
    
    return (
        <ul>
            {listItems.map(item) => <li>{item}</li>}
        </ul>
    );
}

خب، اگه این کد رو خروجی بگیریم می بینیم که با موفقیت کامپوننت های مورد نظر بر اساس تعداد عناصر موجود در آرایه listItems ایجاد میشه اما انگار که مشکلی وجود داره! (تصویر زیر)

 

ارور عدم وجود key یکتا

ارور عدم وجود key یکتا

بسیار عالی، اینطور که مشخصه هر کامپوننتی که با استفاده از حلقه زدن روی یک آرایه ایجاد میشه نیازمند یک پراپرتی key اونم به صورت یونیک است. از اونجایی که میدونیم متد map دارای آرگومان  دومی به نام index هست، ترجیه میدیم همان index رو به عنوان key در هر کامپوننتی که تولید میشه درنظر بگیریم. 😉

const List = () => {
    const listItems = ['Item 1', 'Item 2', 'Item 3'];
    
    return (
        <ul>
            {listItems.map((item, index)) => <li key={index}>{item}</li>}
        </ul>
    );
}

ایندفعه اگه رندر بگیریم متوجه میشیم که ارور Key Props هم برطرف شده.

اما به نظرتون این بهترین راه حل بود؟ (اسپویلر: جواب خیر است) اجازه بدید اندکی در مورد key prop ها بیشتر صحبت کنیم.

 

همه چیز زیر سر بهینه سازی است !!!

ریکت یه کتابخونه قدرتمند برای ساختن رابط کاربری است که اکثر تکنیک های بهینه سازی خودش رو با استفاده از Virtual DOM پیاده سازی می کند.

هر زمان که توی صفحه تغییرات اعمال میشه Virtual DOM با DOM اصلی مقایسه خواهد شد که به این عملیات مقایسه کردن عملیات Diffing میگویند و چون الگوریتم Diffing مورد بحث ما در این مقاله نیست اگه خواستید بیشتر در موردش بدونید میتونید به مقاله ی how diffing algorithm works for elements of different types از سایت خود مراجعه کنید.

بیایید تصور کنیم که ما ماشین هایی با الگوریتم های خاص مقایسه کردن هستیم  و قصد داریم دو حالت مختلف UI یک صفحه رو بررسی کنیم و تغییرات بین دو تا UI رو شناسایی و بروزرسانی انجام دهیم.

ورژن قدیمی UI :

<ul>
  <li>Item 1</li>
  <li>Item 2</li>
</ul>

 

ورژن جدید UI :

<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>

خب، مشخصا خیلی آسونه! درسته؟ ما دو تا <li>Item 1</li> و  دو تا <li>Item 2</li> رو تو درخت UI اول و دوم رو مقایسه می کنیم و متوجه میشیم که هیچ تغییری در این دو وجود ندارد و نیازی هم به بروزرسانی نیست!  اما <li>Item 3</li> در درخت مربوط به UI اول نیست. پس تنها چیزی که به UI اول که همون DOM اصلی ماست اضافه میشه فقط <li>Item 3</li> هست.

خب بیایم یه مقایسه دیگه انجام بدیم.

فرض کنیم UI اول به صورت زیر است:

<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>

و همین طور UI دوم رو به صورت زیر داریم:

<ul>
  <li>Item 4</li>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>

یادآوری، ما فقط یک ماشین هستیم که تنها میتونیم خط به خط li ها رو با هم مقایسه کنیم و نمیتونیم بفهمیم که Item 1 یا Item 2 هنوز وجود دارند یا خیر.

پس این این فرمون <li>Item 1</li> رو با <li>Item 4</li> مقایسه می کنیم و می بینیم که یکسان نیستند و به نظر نیاز به بروزرسانی داره (تگ li موجود در UI اول با li موجود در UI دوم مقایسه میشه) به همین ترتیب <li>Item 2</li> با <li>Item 1</li> برابری نمیکنه و غیره.  پس از پایان مقایسه، نتیجه به صورت زیر حاصل میشه!!!

<ul>
  <li>Item 4</li>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>

اینجاست که نیاز به Key prop ها احساس میشه، در نتیجه مثال بالا رو با دادن key به li های هر دو UI یک بار دیگه تکرار کنیم.

UI اول :

<ul>
  <li key="first">Item 1</li>
  <li key="second">Item 2</li>
  <li key="third">Item 3</li>
</ul>

و همینطور UI دوم:

<ul>
  <li key="fourth>Item 4</li>
  <li key="first">Item 1</li>
  <li key="second">Item 2</li>
  <li key="third">Item 3</li>
</ul>

حالا بجای مقایسه گام به گام المنت ها، خیلی ساده به مقایسه key ها می پردازیم و خیلی ساده متوجه میشیم که کلید های ‘first’, ‘second’ و ‘third’ در هر دو UI مشترک هست و نیازی به بروزرسانی ندارند اما کلید ‘fourth’جدید بوده و تنها عنصر شامل این کلید نیازمند بروزرسانی و نمایش در صفحه می باشد.

پس با این اوصاف فکر کنم دیگه متوجه شده باشید که چرا نیاز داریم از Key Prop ها استفاده کنیم و چرا نمیتونیم از index (همان ایندکسی که به عنوان آرگومان دوم در map داشتیم یا همان ایندکس هر خونه در آرایه) به عنوان key استفاده کنیم؟

استفاده از ایندکس یک آیتم در آرایه به عنوان کلید تنها زمانی خوب عمل می کند که آیتم ها هرگز مرتب سازی مجدد نشوند.

به طورکلی یافتن کلید مناسب آنقدر هم سخت نیست ممکنه اطلاعات درون آرایه رو از دیتابیس گرفته باشید که در این صورت احتمالاً هر کدام از آن ها دارای id منحصر به فردی خواهد بود و میتونید از اون id به عنوان کلید استفاده کنید یچیزی مثل تیکه کد زیر :

<li key={item.id}>{item.name}</li>

 

نتیجه گیری از مبحث Key Prop ها:

هر گاه می خواهید از تعداد زیادی عنصر توسط حلقه، کامپوننت های مختلف بسازید حتماً به هر کدوم از اون کامپوننت ها یک key اختصاص بدید دادن کلید به کامپوننت های تولید شده علاوه بر خلاص شدن از شر ارور های کنسول، موجب جلوگیری از بروز باگ های عجیب و غریب که بعضاً ممکنه یک هفته شما رو الاف خودشون بکنه خواهد شد.

اشتراک گذاری:

مطالب زیر را حتما مطالعه کنید

دیدگاهتان را بنویسید