رندر کردن لیست
اغلب اوقات میخواهید چندین کامپوننت مشابه را از یک مجموعه داده نمایش دهید. میتوانید از متدهای آرایه جاوااسکریپت برای مدیریت یک آرایه از دادهها استفاده کنید. در این صفحه، از متدهای filter() و map() همراه با React استفاده خواهید کرد تا آرایه دادههای خود را فیلتر کرده و به آرایهای از کامپوننتها تبدیل کنید.
You will learn
- چگونه کامپوننتها را با استفاده از متد
()map
جاوااسکریپت از یک آرایه رندر کنیم - چگونه فقط کامپوننتهای خاص را با استفاده از متد
()filter
جاوااسکریپت رندر کنیم - چه زمانی و چرا باید از کلیدهای React استفاده کنیم
رندر کردن دادهها از آرایهها
فرض کنید یک لیست از محتوا دارید.
<ul>
<li>Creola Katherine Johnson: mathematician</li>
<li>Mario José Molina-Pasquel Henríquez: chemist</li>
<li>Mohammad Abdus Salam: physicist</li>
<li>Percy Lavon Julian: chemist</li>
<li>Subrahmanyan Chandrasekhar: astrophysicist</li>
</ul>
تنها تفاوت بین آیتمهای این لیست، محتوای آنها یا دادههایشان است. هنگام ساخت رابطهای کاربری، اغلب نیاز خواهید داشت که چندین نمونه از یک کامپوننت را با دادههای مختلف نمایش دهید؛ از لیست نظرات گرفته تا گالریهای تصاویر پروفایل. در این موارد، میتوانید دادهها را در آبجکتها و آرایههای جاوااسکریپت ذخیره کنید و از متدهایی مانند map()
و filter()
برای رندر کردن لیستی از کامپوننتها استفاده کنید.
در اینجا یک مثال کوتاه برای تولید یک لیست از آیتمها از یک آرایه آورده شده است:
- دادهها را به یک آرایه منتقل کنید
const people = [
'Creola Katherine Johnson: mathematician',
'Mario José Molina-Pasquel Henríquez: chemist',
'Mohammad Abdus Salam: physicist',
'Percy Lavon Julian: chemist',
'Subrahmanyan Chandrasekhar: astrophysicist'
];
- اعضای
people
را به یک آرایه جدید از نودهای JSX به نامlistItems
تبدیل کنید:
const listItems = people.map(person => <li>{person}</li>);
- آرایه
listItems
را در کامپوننت خود داخل یک<ul>
بازگردانید:
return <ul>{listItems}</ul>;
نتیجه نهایی این شد:
const people = [ 'Creola Katherine Johnson: mathematician', 'Mario José Molina-Pasquel Henríquez: chemist', 'Mohammad Abdus Salam: physicist', 'Percy Lavon Julian: chemist', 'Subrahmanyan Chandrasekhar: astrophysicist' ]; export default function List() { const listItems = people.map(person => <li>{person}</li> ); return <ul>{listItems}</ul>; }
توجه کنید که سندباکس بالا یک خطای کنسول نمایش میدهد:
شما یاد میگیرید که چگونه این خطا را در ادامه این صفحه برطرف کنید. قبل از اینکه به آن برسیم، بیایید کمی ساختار به دادههای خود اضافه کنیم.
فیلتر کردن آرایهای از آیتمها
این دادهها میتوانند حتی بیشتر ساختاردهی شوند.
const people = [{
id: 0,
name: 'Creola Katherine Johnson',
profession: 'mathematician',
}, {
id: 1,
name: 'Mario José Molina-Pasquel Henríquez',
profession: 'chemist',
}, {
id: 2,
name: 'Mohammad Abdus Salam',
profession: 'physicist',
}, {
name: 'Percy Lavon Julian',
profession: 'chemist',
}, {
name: 'Subrahmanyan Chandrasekhar',
profession: 'astrophysicist',
}];
فرض کنید میخواهید روشی داشته باشید که فقط افرادی را که حرفهشان 'chemist'
است نمایش دهد. میتوانید از متد filter()
جاوااسکریپت برای بازگشت فقط این افراد استفاده کنید. این متد یک آرایه از آیتمها را میگیرد، آنها را از طریق یک “آزمون” (یک تابع که true
یا false
را برمیگرداند) عبور میدهد و یک آرایه جدید از فقط آیتمهایی که آزمون را پشت سر گذاشتهاند (و true
برگشت دادهاند) باز میگرداند.
شما فقط آیتمهایی را میخواهید که profession
آنها 'chemist'
باشد. تابع “آزمون” برای این کار به شکل (person) => person.profession === 'chemist'
خواهد بود. در اینجا نحوه ترکیب آن آمده است:
- یک آرایه جدید از افراد با حرفه “chemist” به نام
chemists
ایجاد کنید با فراخوانی متدfilter()
بر روی آرایهpeople
و فیلتر کردن بر اساسperson.profession === 'chemist'
:
const chemists = people.filter(person =>
person.profession === 'chemist'
);
- حالا بر روی
chemists
از متدmap()
استفاده کنید:
const listItems = chemists.map(person =>
<li>
<img
src={getImageUrl(person)}
alt={person.name}
/>
<p>
<b>{person.name}:</b>
{' ' + person.profession + ' '}
known for {person.accomplishment}
</p>
</li>
);
- در نهایت، آرایه
listItems
را از کامپوننت خود بازگردانید:
return <ul>{listItems}</ul>;
import { people } from './data.js'; import { getImageUrl } from './utils.js'; export default function List() { const chemists = people.filter(person => person.profession === 'chemist' ); const listItems = chemists.map(person => <li> <img src={getImageUrl(person)} alt={person.name} /> <p> <b>{person.name}:</b> {' ' + person.profession + ' '} known for {person.accomplishment} </p> </li> ); return <ul>{listItems}</ul>; }
حفظ ترتیب آیتمهای لیست با استفاده از key
توجه کنید که همهی سندباکسهای بالا یک خطا در کنسول نمایش میدهند:
شما باید به هر آیتم آرایه یک key
بدهید — یک رشته یا عدد که آن را به طور منحصر به فرد در میان سایر آیتمها در آن آرایه شناسایی کند:
<li key={person.id}>...</li>
کلیدها به React میگویند که هر کامپوننت مربوط به کدام آیتم آرایه است، تا بتواند آنها را بعداً مطابقت دهد. این موضوع زمانی اهمیت پیدا میکند که آیتمهای آرایه شما ممکن است جابجا شوند (برای مثال به دلیل مرتبسازی)، وارد شوند یا حذف شوند. یک key
بهخوبی انتخاب شده به React کمک میکند تا دقیقاً متوجه شود چه اتفاقی افتاده است و بهروزرسانیهای صحیحی را در درخت DOM انجام دهد.
به جای ایجاد کلیدها به صورت آنی، باید آنها را در دادههای خود گنجانید:
export const people = [{ id: 0, // Used in JSX as a key name: 'Creola Katherine Johnson', profession: 'mathematician', accomplishment: 'spaceflight calculations', imageId: 'MK3eW3A' }, { id: 1, // Used in JSX as a key name: 'Mario José Molina-Pasquel Henríquez', profession: 'chemist', accomplishment: 'discovery of Arctic ozone hole', imageId: 'mynHUSa' }, { id: 2, // Used in JSX as a key name: 'Mohammad Abdus Salam', profession: 'physicist', accomplishment: 'electromagnetism theory', imageId: 'bE7W1ji' }, { id: 3, // Used in JSX as a key name: 'Percy Lavon Julian', profession: 'chemist', accomplishment: 'pioneering cortisone drugs, steroids and birth control pills', imageId: 'IOjWm71' }, { id: 4, // Used in JSX as a key name: 'Subrahmanyan Chandrasekhar', profession: 'astrophysicist', accomplishment: 'white dwarf star mass calculations', imageId: 'lrWQx8l' }];
Deep Dive
وقتی هر آیتم نیاز به رندر کردن چندین نود DOM داشته باشد، چه کار میکنید؟
سینتکس کوتاه <>...</>
Fragment به شما اجازه نمیدهد که کلیدی را ارسال کنید، بنابراین شما باید آنها را یا در یک <div>
واحد گروهبندی کنید، یا از سینتکس کمی بلندتر و واضحتر <Fragment>
استفاده کنید:
import { Fragment } from 'react';
// ...
const listItems = people.map(person =>
<Fragment key={person.id}>
<h1>{person.name}</h1>
<p>{person.bio}</p>
</Fragment>
);
فرگمنتها از DOM ناپدید میشوند، بنابراین این کار یک لیست صاف از <h1>
, <p>
, <h1>
, <p>
, و به همین ترتیب تولید خواهد کرد.
کجا باید کلید
خود را بگیرید؟
منابع مختلف داده، منابع مختلفی برای کلیدها فراهم میکنند:
- دادهها از یک پایگاه داده: اگر دادههای شما از یک پایگاه داده میآید، میتوانید از کلیدها/شناسههای پایگاه داده استفاده کنید که به طور طبیعی منحصر به فرد هستند.
- دادههای تولید شده به صورت محلی: اگر دادههای شما به صورت محلی تولید و ذخیره میشود (مثلاً یادداشتها در یک اپلیکیشن یادداشتبرداری)، از یک شمارنده افزایشی،
crypto.randomUUID()
یا یک پکیج مانندuuid
هنگام ایجاد آیتمها استفاده کنید.
قوانین کلیدها
- کلیدها باید در میان دسته خود منحصر به فرد باشند. اما استفاده از کلیدهای مشابه برای نودهای JSX در آرایههای متفاوت اشکالی ندارد.
- کلیدها نباید تغییر کنند زیرا این کار هدف آنها را بیاثر میکند! از تولید آنها در حین رندرینگ خودداری کنید.
چرا React به کلیدها نیاز دارد؟
تصور کنید که فایلها در دسکتاپ شما نام نداشته باشند. در عوض، شما آنها را بر اساس ترتیبشان ارجاع میدهید — فایل اول، فایل دوم و به همین ترتیب. شاید به این موضوع عادت کنید، اما زمانی که یک فایل حذف شود، این موضوع گیجکننده میشود. فایل دوم به فایل اول تبدیل میشود، فایل سوم به فایل دوم و همینطور ادامه مییابد.
نام فایلها در یک پوشه و کلیدهای JSX در یک آرایه هدف مشابهی دارند. آنها به ما این امکان را میدهند که یک آیتم را بین همنیاکانش به طور منحصر به فرد شناسایی کنیم. یک کلید بهخوبی انتخاب شده اطلاعات بیشتری نسبت به موقعیت داخل آرایه فراهم میکند. حتی اگر موقعیت به دلیل مرتبسازی تغییر کند، کلید به React این امکان را میدهد که آیتم را در طول عمر آن شناسایی کند.
Recap
در این صفحه شما آموختید:
- چگونه دادهها را از کامپوننتها خارج کرده و به ساختارهای دادهای مانند آرایهها و اشیاء منتقل کنید.
- چگونه مجموعههایی از کامپوننتهای مشابه با استفاده از متد
map()
در جاوااسکریپت ایجاد کنید. - چگونه آرایههایی از آیتمهای فیلتر شده با استفاده از متد
filter()
در جاوااسکریپت بسازید. - چرا و چگونه باید برای هر کامپوننت در یک مجموعه
key
را تنظیم کنید تا React بتواند هر کدام را پیگیری کند حتی اگر موقعیت یا دادههای آنها تغییر کند.
Challenge 1 of 4: تقسیم یک لیست به دو بخش
این مثال یک لیست از تمام افراد را نشان میدهد.
آن را تغییر دهید تا دو لیست جداگانه یکی پس از دیگری نمایش داده شود: شیمیدانها و بقیه افراد. همانطور که قبلاً اشاره شد، میتوانید تعیین کنید که آیا یک شخص شیمیدان است یا خیر با بررسی اینکه person.profession === 'chemist'
.
import { people } from './data.js'; import { getImageUrl } from './utils.js'; export default function List() { const listItems = people.map(person => <li key={person.id}> <img src={getImageUrl(person)} alt={person.name} /> <p> <b>{person.name}:</b> {' ' + person.profession + ' '} known for {person.accomplishment} </p> </li> ); return ( <article> <h1>Scientists</h1> <ul>{listItems}</ul> </article> ); }