چرا در React معمولا از متد map برای حلقه زدن استفاده میکنیم؟
همیشه عمیق شدن در ابزارهایی که ازشون استفاده میکنیم پراهمیت بوده و درک بهتر اونها تاثیر زیادی توی عملکرد ما به عنوان توسعهدهنده میذاره. برای مثال وقتی داریم با React کار میکنیم، بارها و بارها پیش میاد که بخوایم برای رندر کردن و نمایش دادن لیستی از اطلاعات از متد map استفاده میکنیم. خوبه که این سوال برامون پیش بیاد که چرا map
و اینکه اصلا این متد چی برمیگردونه و ریاکت چجوری اون رو به کد قابل فهم برای مرورگر تبدیل میکنه.
لیستها در React و رندرکردن آنها
به طور خاص وقتی از لیست صحبت میکنیم منظورمون همون آرایه هست. معمولا دادههایی که دریافت میکنیم و قصد نمایش اونها رو در یک کامپوننت داریم به صورت لیستی در قالب یک آرایه هستن. دو متد کاربری map
و filter
مستقیم روی آرایه اعمال میشن و به عنوان خروجی هم آرایه برمیگردونن. ما از این دو متد توی React زیاد استفاده میکنیم.
خوبه که بدونین React در پسزمینه سازوکاری برای نمایش اطلاعات توی JSX داره، به این صورت که هر آیتم موجود در یک لیست رو یک کامپوننت در نظر میگیره. حتی مثلا یه تگ ساده div
هم به نوعی یک کامپوننت built-in توی React محسوب میشه.
تا حالا سعی کردین یه چیزی شبیه به این توی JSX بنویسین:
<ul>
<li>یک آیتم تست</li>
<li>یک آیتم تست دیگه</li>
<li>اینم یکی دیگه</li>
</ul>
همه چیز درسته و مشکلی نیست. حالا اگه بخوایم چنین لیستی رو از روی یک آرایه رندر کنیم یه چیزی شبیه به این مینویسیم:
const items = [
'یک آیتم تست',
'یک آیتم تست دیگه',
'اینم یکی دیگه'
]
export function App() {
return (
<div>
<ul>
{items.map(item => <li>{item}</li>)}
</ul>
</div>
);
}
همونطور که میدونید عدم وجود پراپ key
روی تگ li باعث برخورد به Warning توی کنسول میشه که هممون دیدیمش و میگه باید هر عضو از لیست یک key منحصر بفرد داشته باشه. در واقع Virtual DOM توی ریاکت با این کلید متوجه میشه که لیستمون تغییری داشته یا نه که اگر داشت دوباره کامپوننت رو ریرندر و بروزرسانی بکنه. دلیل اینکه در حالت دوم به key نیاز داریم ولی قبلی نه، اینه که این احتمال وجود داره که آرایه ورودی تغییر بکنه ولی در حالت اول صراحتا خروجی به JSX داده شده و تکلیف مشخصه.
پس زمانی که شما یک لیست استاتیک مثل حال اول دارید، React میدونه که این لیست ثابته و نیازی به مدیریت تغییرات یا بررسی مجدد نداره. اما زمانی که لیست از روی دادههای داینامیک (مثل آرایه) ساخته میشه، React به key
نیاز داره تا بتونه تغییرات را به درستی پیگیری کنه و تفاوتها را شناسایی کنه.
اون تیکه از رندر شدن لیست مثل زیر میتونه بازنویسی بشه با فرض اینکه مقدار key
کاملا منحصربفرده و با بقیه اعضا فرق داره. (معمولا از یه شاخصه دیگه مثل id برای اون استفاده میشه ولی اینجا لیستمون از دادههای خام رشته تشکیل شده و آیدی نداریم):
<ul>
{items.map(item => <li key={item}>{item}</li>)}
</ul>
همه اینارو گفتم که به یه درکی ابتدایی از نوع نگاه React به لیستها برسیم و متوجه یه نکته دیگه هم بشیم. همونطور که میدونیم چیزی که متد map ریترن میکنه یه آرایه است به طول همون آرایه ای که به عنوان ورودی گرفته بود و اگه دقت کرده باشین ما مستقیم یک آرایه رو درون JSX برگردوندیم و React خودش اون رو به کامپوننت تبدیل کرد. جالبه، نه؟
حتی اگه یه آرایه مستقیم هم بنویسیم به راحتی و بدون نیاز به map رندر گرفته میشه. مثل این:
const items = [
'یک آیتم تست',
'یک آیتم تست دیگه',
'اینم یکی دیگه'
]
export function App() {
return (
<div>
<ul>
{items}
</ul>
</div>
);
}
به صورت خودکار ریاکت عناصر داخل آرایه items
رو میچسبونه بهم و توی خروجی نمایش میده بدون هیچ مشکلی. حالا میشه واسه نمایش بهتر برای اینکه متنها بهم نچسبن از متد join توی جاوااسکریپت استفاده کرد:
{items.join(' - ')}
پس متوجه شدیم خود ریاکت آرایههای ما رو رندر میکنه و برمیگردونه و باز دوباره مثل همون کد اول که لیست صراحتا نوشته شده، خطایی بخاطر کلیدها هم نداریم.
map آرایه برمیگردونه، ما هم آرایه میخوایم...
با این توضیحات معلوم شد که ما برای نمایش دادن یه لیست توی React تهش یه آرایه میخوایم. دوستمون map
برامون همین کار رو میکنه و ما با استفاده از اون در واقع داریم با یک تیر دو تا نشون میزنیم. در وهله اول روی آرایه iterate میکنیم و اون رو دستکاری و آپدیت میکنیم و در وهله دوم یه آرایه در خروجی میگیریم که مورد نیاز React برای نمایش هستش. به این ترتیب نیازی به استفاده از حلقهها و forEach و امثال اونا نیست.
فقط map نیست
علاوه بر متد map متد filter
هم به همین ترتیب عمل میکنه با این تفاوت که بخشی از لیست مورد نظر رو برمیگردونه. در صورتی که به نمایش کل آرایه ورودی نیاز نداریم و فقط یک بخش مورد نظر از اون لیست رو بخوایم میتونیم از متد filter استفاده کنیم. این متد یک کالبک میگیره که شامل شرط مورد نظر برای فیلتر کردن دادههاست و در نهایت عناصر فیلترشده رو به شکل یه آرایه برمیگردونه.
نتیجهگیری
توی این مقاله سعی کرد م خیلی ساده به چند سازوکار ریاکت در نوع نگرشش به دیتا و رندرکردن اونها اشاره کنم. مسائلی که گفته شده ساده هستن ولی دونستن اونا مفیده. همچنین به چرایی استفاده از متد map برای حلقهزدن و گشتن روی اطلاعات اشاره شد که دلیل اصلی اون به خاطر رسیدن به آرایه به عنوان خروجی بود. اگر شما هم نکتهای مازاد بر مواردی که گفته شد میدونین، حتما از طریق نظرات پست باهام به اشتراک بذارین.