رندرکردن شرطی
کامپوننتهای شما معمولا بسته به شرایط مختلف نیاز به نمایش چیزهای مختلفی دارند. در ریاکت، میتوانید JSX را با سینتکس جاوااسکریپت با استفاده از دستوراتی مانند if
، &&
، و ? :
به صورت شرطی رندر کنید.
You will learn
- نحوه برگرداندن JSX های مختلف بسته به یک شرط
- نحوه گنجاندن یا حذف کردن شرطی یک قطعه از JSX
- میانبرهای سینتکسی شرطی رایج که در کدهای ریاکت با آنها مواجه خواهید شد
برگرداندن شرطی JSX
فرض کنید یک کامپوننت PackingList
دارید که چندین Item
را رندر میکند، که میتوان آنها را بهعنوان بستهبندیشده یا غیر بستهبندیشده علامتگذاری کرد:
function Item({ name, isPacked }) { return <li className="item">{name}</li>; } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
توجه داشته باشید که برای برخی از کامپوننتهای props ،isPacked
آن ها به جای true ،false داده شده است. شما میخواهید اگر isPacked={true}
باشد، یک علامت (✔) به موارد بستهبندی شده اضافه کنید.
می توانید این را به عنوان یک عبارت if
/else
statement بنویسید:
if (isPacked) {
return <li className="item">{name} ✔</li>;
}
return <li className="item">{name}</li>;
اگر prop isPacked
، true
باشد، این کد یک درخت JSX متفاوت را برمیگرداند. با این تغییر، برخی از آیتم ها در انتها علامت چکمارک میگیرند:
function Item({ name, isPacked }) { if (isPacked) { return <li className="item">{name} ✔</li>; } return <li className="item">{name}</li>; } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
سعی کنید آنچه را که در هر کدام از حالتها بازگردانده می شود ویرایش کنید و ببینید نتیجه چگونه تغییر می کند!
به نحوه ایجاد منطق شاخهای با دستورات if
و return
جاوا اسکریپت توجه کنید. در ریاکت، control flow (مانند شرایط) توسط جاوا اسکریپت مدیریت می شود.
برنگرداندن چیزی به صورت شرطی با null
در برخی شرایط، اصلاً نمی خواهید چیزی را رندر کنید. مثلاً وقتی اصلاً نمیخواهید موارد بستهبندی شده را نشان دهید. یک کامپوننت باید چیزی را برگرداند. در این مورد، می توانید null
را برگردانید:
if (isPacked) {
return null;
}
return <li className="item">{name}</li>;
اگر true ،isPacked
باشد، کامپوننت چیزی را بر نمیگرداند، null
. در غیر این صورت، JSX را برای رندر برمی گرداند.
function Item({ name, isPacked }) { if (isPacked) { return null; } return <li className="item">{name}</li>; } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
در عمل، برگرداندن null
از یک کامپوننت رایج نیست، زیرا ممکن است توسعهدهندهای را که تلاش میکند آن را رندر کند، سورپرایز کند. بیشتر اوقات، شما به صورت شرطی کامپوننت را در JSX کامپوننت پدر قرار می دهید یا حذف می کنید. در اینجا نحوه انجام این کار آمده است!
شاملشدن JSX به صورت شرطی
در مثال قبلی، شما کنترل کردید که کدام درخت JSX (در صورت وجود!) توسط کامپوننت بازگردانده شود. ممکن است قبلاً متوجه مقداری تکرار در خروجی رندر شده باشید:
<li className="item">{name} ✔</li>
بسیار مشابه است با
<li className="item">{name}</li>
هر دو شاخه شرطی <li className="item">...</li>
را برمیگردانند:
if (isPacked) {
return <li className="item">{name} ✔</li>;
}
return <li className="item">{name}</li>;
اگرچه این تکرار مضر نیست، اما میتواند نگهداری کد شما را سختتر کند. اگر بخواهید className
را تغییر دهید چه؟ شما باید این کار را در دو جا از کد خود انجام دهید! در چنین شرایطی، میتوانید به صورت شرطی، کمی JSX اضافه کنید تا کدتان بیشتر DRY شود.
عملگر شرطی (سه تایی) (? :
)
جاوا اسکریپت یک سینتکس فشرده برای نوشتن یک عبارت شرطی دارد — عملگر شرطی یا “عملگر سه تایی”.
به جای این:
if (isPacked) {
return <li className="item">{name} ✔</li>;
}
return <li className="item">{name}</li>;
می توانید این را بنویسید:
return (
<li className="item">
{isPacked ? name + ' ✔' : name}
</li>
);
شما می توانید آن را به صورت “اگر isPacked
درست است، سپس (?
) name + ' ✔'
را رندر کنید، در غیر این صورت (:
) name
را اجرا کنید ” بخوانید.
Deep Dive
اگر از یک پسزمینه برنامهنویسی شیگرا میآیید، ممکن است فرض کنید که دو مثال بالا به طور ظاهری متفاوت هستند، زیرا یکی از آنها ممکن است دو “نمونه” متفاوت از <li>
ایجاد کند. اما المنتهای JSX “نمونه” نیستند زیرا هیچ حالت داخلی ندارند و نودهای واقعی DOM نیستند. آنها توصیف های سبک وزن هستند، مانند blueprintها. بنابراین، این دو مثال، در واقع کاملاً معادل هستند. نگهداری و بازنشانی وضعیت به تفصیل درباره اینکه چگونه این، کار میکند توضیح میدهد.
حال فرض کنید میخواهید متن مورد تکمیلشده را در یک تگ HTML دیگری مانند <del>
بپیچید تا روی آن خط بکشید. میتوانید حتی خطوط جدید و پرانتز بیشتری اضافه کنید تا در هر یک از موارد، JSX بیشتری را راحتتر جاسازی کنید.
function Item({ name, isPacked }) { return ( <li className="item"> {isPacked ? ( <del> {name + ' ✔'} </del> ) : ( name )} </li> ); } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
این سبک برای شرایط ساده به خوبی کار می کند، اما از آن در حد اعتدال استفاده کنید. اگر کامپوننتهای شما با نشانهگذاریهای شرطی بیش از حد تودرتو، آشفته میشوند، برای تمیز کردن این موارد، کامپوننت فرزند را جدا کنید. در ریاکت، نشانه گذاری بخشی از کد شما است، بنابراین می توانید از ابزارهایی مانند متغیرها و توابع برای مرتب کردن عبارات پیچیده استفاده کنید.
عملگر منطقی AND (&&
)
یکی دیگر از میانبرهای رایجی که با آن مواجه خواهید شد، عملگر منطقی AND (&&
) جاوا اسکریپت است. در داخل کامپوننت های ریاکت، اغلب زمانی میآید که می خواهید مقداری JSX را وقتی شرطی درست است، رندر کنید، یا هیچ چیزی را رندر نکنید. با &&
، فقط در صورتی می توانید علامت را به صورت شرطی ارائه دهید که true
،isPacked
باشد:
return (
<li className="item">
{name} {isPacked && '✔'}
</li>
);
می توانید این را به صورت “اگر isPacked
، آنگاه (&&
) علامت چکمارک را ارائه دهید، در غیر این صورت، هیچ چیزی را رندر نکنید”، بخوانید.
اینجا در عمل داریم:
function Item({ name, isPacked }) { return ( <li className="item"> {name} {isPacked && '✔'} </li> ); } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
یک عبارت && جاوااسکریپت اگر سمت چپ (شرط ما) true
است، مقدار سمت راست خود (در مورد ما، علامت چکمارک) را برمی گرداند. اما اگر شرط false
باشد، کل عبارت false
می شود. ریاکت false
را به عنوان “سوراخ” در درخت JSX، درست مانند null
یا undefined
در نظر میگیرد و هیچ چیزی را در جای آن ارائه نمیکند.
انتساب (assign) شرطی JSX به یک متغیر
وقتی میانبرها مانع نوشتن کد ساده می شوند، سعی کنید از عبارت if
و یک متغیر استفاده کنید. می توانید متغیرهای تعریف شده با let
را مجدداً assign کنید، بنابراین با رندرکردن محتوای پیش فرضی که می خواهید نمایش دهید شروع کنید، نام:
let itemContent = name;
از عبارت if
برای تخصیص (assign) مجدد عبارت JSX به itemContent
استفاده کنید، اگر true
،isPacked
باشد:
if (isPacked) {
itemContent = name + " ✔";
}
آکولادها “پنجرهای به جاوا اسکریپت” باز می کنند. متغیر را با آکولاد در درخت JSX بازگشتی قرار دهید، قرار دادن عبارت محاسبه شده قبلی در JSX:
<li className="item">
{itemContent}
</li>
این سبک طولانیترین است، اما انعطاف پذیرترین هم میباشد. اینجا در عمل داریم:
function Item({ name, isPacked }) { let itemContent = name; if (isPacked) { itemContent = name + " ✔"; } return ( <li className="item"> {itemContent} </li> ); } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
مانند قبل، این نه تنها برای متن، بلکه برای JSX دلخواه نیز کار می کند:
function Item({ name, isPacked }) { let itemContent = name; if (isPacked) { itemContent = ( <del> {name + " ✔"} </del> ); } return ( <li className="item"> {itemContent} </li> ); } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }
اگر با جاوا اسکریپت آشنایی ندارید، این تنوع سبک در ابتدا ممکن است طاقتفرسا به نظر برسد. با این حال، یادگیری آنها به شما کمک می کند تا هر کد جاوا اسکریپت را بخوانید و بنویسید — و نه فقط کامپوننتهای ریاکت را! یکی را که برای شروع ترجیح می دهید انتخاب کنید و اگر فراموش کردید که بقیه چگونه کار می کنند، دوباره با این مرجع مشورت کنید.
Recap
- در ریاکت، منطق شاخهبندی را با جاوا اسکریپت کنترل میکنید.
- می توانید یک عبارت JSX را به صورت شرطی با عبارت
if
برگردانید. - می توانید به صورت شرطی JSX را در یک متغیر ذخیره کنید و سپس با استفاده از آکولاد آن را در داخل JSX دیگری قرار دهید.
- در JSX، عبارت
{cond ? <A /> : <B />}
به معنای “اگرcond
، آنگاه<A />
را رندر کنید، در غیر این صورت<B />
را” است. - در JSX، عبارت
{cond && <A />}
به معنای “اگرcond
، آنگاه<A />
را رندر کنید، در غیر این صورت هیچی” است. - میانبرها رایج هستند، اما اگر
if
ساده را ترجیح می دهید، نیازی به استفاده از آنها ندارید.
Challenge 1 of 3: نمادی برای مواردی که کاملنشده با ? :
نشان بده
اگر true
،isPacked
نباشد، از عملگر شرطی (cond ? a : b
) برای رندرکردن ❌ استفاده کن.
function Item({ name, isPacked }) { return ( <li className="item"> {name} {isPacked && '✔'} </li> ); } export default function PackingList() { return ( <section> <h1>Sally Ride's Packing List</h1> <ul> <Item isPacked={true} name="Space suit" /> <Item isPacked={true} name="Helmet with a golden leaf" /> <Item isPacked={false} name="Photo of Tam" /> </ul> </section> ); }