تعریف حلقه روی آرایه ها در React – راهنمای کاربردی


زمانی که مشغول ساخت هر نوع وب اپلیکیشن هستیم، کاملاً محتمل است که نیاز به مدیریت آرایهای از دادهها داشته باشیم. در این مقاله، شیوه تعریف حلقه روی آرایه دادهها با استفاده از بهترین رویههای ریاکت را مرور میکنیم. به این منظور از مثالهایی واقعی بهره میگیریم که میتوانید از آنها در برنامههای واقعی خود برای تعریف حلقه روی آرایه ها در React استفاده کنید.
آیا تاکنون از تابع map استفاده کردهاید؟
تابع map در جاوا اسکریپت نسخه ES2015 معرفی شده است. این تابع عموماً فرایند تعریف حلقه را سادهتر کرده و نیاز به استفاده از حلقه for و تابع forEach را مرتفع ساخته است. در حال حاضر برخی تفاوتها بین حلقه for و ForEach برای map وجود دارد، اما فعلاً قصد نداریم به آنها بپردازیم. ریاکت شدیداً توصیه میکند که از تابع map استفاده کنید و این توصیه صرفاً به خاطر سادگی آن نیست بلکه بیشتر به این جهت است که به جای تلاش برای تغییر یا بازنویسی دادههای موجود، یک آرایه جدید از دادهها میسازد.
نکته دوم بسیار مهم است. اگر در مورد شیوه استفاده از تابعهای map مطمئن نیستید، پیشنهاد میکنیم مطلب زیر را مطالعه کنید.
تعریف حلقه روی یک آرایه از آیتمها در سبد خرید
تصور کنید میخواهیم یک وبسایت فروشگاهی بسازیم که در آن لباس به فروش میرسد. اپلیکیشن ما احتمالاً یک سبد خرید دارد که آیتمها به آن اضافه میشوند. بنابراین در آغاز، سبد خرید ما باید چیزی مانند زیر باشد:
1let shoppingCart = [];
اما پس از اینکه آیتمها به آن اضافه شدند، میتواند چیزی مانند زیر باشد:
let shoppingCart = [ {id: 35، item: 'jumper'، color: 'red'، size: 'medium'، price: 20}، {id: 42، item: 'shirt'، color: 'blue'، size: 'medium'، price: 15}، {id: 71، item: 'socks'، color: 'black'، size: 'all'، price: 5}، ]
اکنون میخواهیم در صفحه خرید این آیتمها را در خروجی ارائه کنیم به طوری که کاربر بتواند سفارشهای خود را ببیند. دو روش بسیار مشابه برای این کار وجود دارد.
درون سازنده کلاس App، اقدام به ساخت this.items میکنیم و آن را به this.state.cart انتساب میدهیم. توجه داشته باشید که این جایی است که آیتمهای فروشگاه به سبد خرید اضافه شدهاند. سپس از تابع ES2015 به نام map برای تعریف حلقه روی همه آیتمهای موجود در this.state.cart استفاده میکنیم.
دو پارامتر باید به تابع map خود ارسال کنیم. پارامتر اول آیتم است که متناظر با آیتم منفرد درون آرایه this.state.cart است. پارامتر دوم کلید است که React از آن برای کمک به رندر کننده جهت حفظ رد هر آیتم منفرد استفاده میکند. چنان که احتمالاً متوجه شدهاید ما هیچ کلیدی درون this.state.cart تنظیم نکردهایم و از این رو id آیتم را به عنوان کلید ارسال میکنیم و به صورت item.id درون تابع map ارجاع میدهیم. در هر حال در ادامه یک تگ خروجی <li> ارائه میکنیم که درون آن {item.name} قرار دارد.
در ادامه به بررسی سریع طرز کار این کد میپردازیم:
1this.items = this.state.cart.map((item, key) =>
2 <li key={item.id}>{item.name}</li>
3);
در ادامه کد زمانی که میخواهیم از آن استفاده کنیم کافی است یک تگ بیرونی <ul> ایجاد کنیم و this.items inside را به صورت زیر درون آن قرار دهیم:
1<ul>
2 {this.items}
3</ul>
به این ترتیب صفحه ما هر آیتمی را که در سبد خرید باشد به صورت یک آیتم یکتای <li> رندر میکند. روش دوم که با آن میتوان این وضعیت را مدیریت کرد، مشابه روش اول است و احتمالاً برای شما کمی آشناتر خواهد بود. در این روش به جای قرار دادن بلوک کد this.item درون سازنده کلاس، میتوانیم آن را به صورت زیر صرفاً در ابتدای تابع ()render قرار دهیم:
1render() {
2 const items = this.state.cart.map((item, key) =>
3 <li key={item.id}>{item.name}</li>
4 );
بدین ترتیب میتوانیم از ساختار const سنتی (یا در صورت ترجیح از var) استفاده کنیم. اگر چنین بکنیم، معنای دیگر آن این خواهد بود که میتوانیم کد زیر را به جای قبلی بنویسیم:
1<ul>
2 {items}
3</ul>
اکنون برخی افراد استدلال میکنند که نباید تابع ()render را آلوده کرد، اما وقتی کدی نسبتاً ساده مینویسید که پیچیدگی خارقالعادهای ندارد، این مسئله اهمیت چندانی ندارد. ما توصیه میکنیم که هر روشی که برای شما مناسبتر است را انتخاب کنید. زمانی که در React پیشرفت بیشتری داشتید، برای خود یک سبک کدنویسی پیدا میکنید که بیشترین مطابقت را با پروژه شما خواهد داشت.
اینک سؤال این است که چگونه میتوان لیست را با استفاده از حلقهها رندر کرد. اگر بخواهیم روی دادهها حلقهای تعریف کنیم تا کامپوننتهای فرزند زیادی در خروجی ارائه کنیم چطور؟ این کار چگونه قابل انجام است؟
پاسخ در واقع کاملاً ساده است و شباهت زیادی به آن چه قبلاً اجرا کردیم، دارد. تصور کنید فروشگاه ما آیتمهای زیر را دارد:
1shop: [
2 {id: 35, name: 'jumper', color: 'red', price: 20},
3 {id: 42, name: 'shirt', color: 'blue', price: 15},
4 {id: 56, name: 'pants', color: 'green', price: 25},
5 {id: 71, name: 'socks', color: 'black', price: 5},
6 {id: 72, name: 'socks', color: 'white', price: 5},
7]
برای این که تصویر روشنتری داشته باشید، این فروشگاه درون this.state یعنی درون یک «سازنده» (constructor) قرار دارد و به صورت زیر است:
1class App extends Component {
2 constructor(props) {
3 super(props);
4 this.state = {
5 cart: [],
6 shop: [
7 {id: 35, name: 'jumper', color: 'red', price: 20},
8 {id: 42, name: 'shirt', color: 'blue', price: 15},
9 {id: 56, name: 'pants', color: 'green', price: 25},
10 {id: 71, name: 'socks', color: 'black', price: 5},
11 {id: 72, name: 'socks', color: 'white', price: 5},
12 ]
13 }
14 }
بنابراین آیتمهای فروشگاه ما حاضر هستند و اکنون میخواهیم یک کامپوننت فرزند بسازیم که Item.js را فراخوانی میکند. کل فایل کامپوننت به صورت زیر است:
1import React, {Component} from 'react';
2
3class Item extends Component {
4 render() {
5 return (
6 <div>
7 <p>{this.props.item.name}</p>
8 <p>{this.props.item.color}</p>
9 <p>${this.props.item.price}</p>
10 </div>
11 );
12 }
13}
14
15export default Item;
اگر مطمئن نیستید، ما this.props.item را فراخوانی میکنیم، زیرا زمانی که آن را درون کامپوننت والد فراخوانی میکنیم، this.state.item را به آن ارسال میکنیم. این کار ممکن است کمی عجیب به نظر برسد، اما آن را تحمل کنید چون در ادامه معنای آن را متوجه خواهید شد.
اگر به حلقه خود بازگردیم، این چیزی است که برای تعریف حلقه روی آیتمهای فروشگاه خود نوشتهایم:
1<h3>Items for sale</h3>
2{this.state.shop.map((item, key) =>
3 <Item item={item} key={item.id} />
4)}
چنان که میبینید، این تقریباً همان مفهومی است که قبلاً مورد استفاده قرار دادیم. تنها تفاوت در این است که در اینجا به جای خروجی دادن تگهای <li> اکنون مشغول ارائه تگهای </ Item> در خروجی هستیم که مربوط به کامپوننت Item.js است که قبلاً اشاره کردیم. کار به همین سادگی است.
بنابراین زمانی که this.props.item را درون کامپوننت Item.js فراخوانی میکنیم یک ارجاع به </ {Item item={item} key={item.id}> و به طور خاصتر {item={item محسوب میشود. بنابراین اگر ما این {product={item را فراخوانی کنیم، به جای آن میتوانیم به this.props.product ارجاع بدهیم.
ممکن است متوجه شده باشید که ما کل کارکرد را درون آکولادها قرار دادهایم این امر مستلزم این است که ریاکت بتواند درک کند که میخواهیم یک تابع را تعریف کنیم و نه این که متن ساده را رندر کنیم.
نکته دیگری که باید در اینجا اشاره کنیم آن است که روشهای مختلفی برای تعریف حلقه روی دادهها وجود دارند که همگی قابل تعویض با یکدیگر هستند. بنابراین اگر میخواهید روی یک ارائه از کامپوننتهای فرزند حلقهای تعریف کنید اما ترجیح میدهید از روش اول که در این نوشته مطرح کردیم، استفاده کنید، این کار کاملاً امکانپذیر است. توجه کنید که در نهایت همه اینها کدهای معمولی جاوا اسکریپت هستند.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای جاوا اسکریپت
- مجموعه آموزشهای برنامهنویسی
- آموزش ری اکت (React) — مجموعه مقالات مجله فرادرس
- ری اکت (React) — راهنمای جامع برای شروع به کار
- آموزش React.js در کمتر از ۵ دقیقه — از صفر تا صد
==