Conditional Rendering و اثر آن روی State
در فصل اول با Conditional Rendering آشنا شدیم: نمایش یا عدم نمایش بخشی از JSX بر اساس یک شرط. اما حالا که Reconciliation و Identity را میشناسیم، میتوانیم دقیقتر ببینیم Conditional Rendering چه اثری روی State کامپوننتهایی دارد که نمایش داده یا پنهان میشوند.
حذف کامل یک کامپوننت از JSX، یعنی Unmount
وقتی یک عنصر با استفاده از && یا عملگر شرطی، بهطور کامل از خروجی JSX کنار گذاشته میشود (نه فقط با CSS پنهان شود)، React آن را کاملاً از درخت حذف میکند. این یعنی Unmount: State آن کامپوننت از بین میرود و اگر دوباره شرط برقرار شود، یک نمونه کاملاً تازه ساخته میشود.
function App() {
const [showDetails, setShowDetails] = useState(true);
return (
<div>
{showDetails && <DetailsForm />}
<button onClick={() => setShowDetails(!showDetails)}>
نمایش/پنهان
</button>
</div>
);
}
در این کد، هر بار که showDetails به false برود و دوباره به true برگردد، DetailsForm کاملاً از نو Mount میشود؛ هر متنی که کاربر قبلاً در آن تایپ کرده بود، از بین رفته است. این دقیقاً همان رفتاری است که در فصل یازدهم، درباره حذف یک گره از درخت و ساخت دوباره آن، دیدیم.
راهحل جایگزین: پنهان کردن با CSS، بدون حذف از درخت
اگر هدف این است که State حفظ شود، اما کامپوننت موقتاً از دید کاربر پنهان باشد، میتوان بهجای حذف کامل از JSX، فقط ظاهر آن را با CSS پنهان کرد:
function App() {
const [showDetails, setShowDetails] = useState(true);
return (
<div>
<div style={{ display: showDetails ? "block" : "none" }}>
<DetailsForm />
</div>
<button onClick={() => setShowDetails(!showDetails)}>
نمایش/پنهان
</button>
</div>
);
}
در این نسخه، DetailsForm همیشه در درخت باقی میماند؛ فقط ظاهرش با display: none از دید کاربر کنار میرود. چون از دید React نوع و موقعیت این کامپوننت هیچوقت عوض نشده، State آن، حتی در حالت پنهان، دستنخورده باقی میماند.
این یک تصمیم طراحی است، نه یک قانون ثابت
هیچکدام از این دو روش همیشه «درستتر» نیست؛ انتخاب به نیاز واقعی بستگی دارد. اگر پنهان شدن موقتی است و بازگشت به همان حالت قبلی طبیعی به نظر میرسد (مثل یک Tab یا یک Accordion که کاربر مدام بینشان جابهجا میشود)، حفظ State با CSS منطقیتر است. اگر پنهان شدن به معنای واقعی «پایان یک کار» است (مثل بستن کامل یک فرم بعد از ارسال)، حذف کامل و از دست رفتن State، رفتار درستی است.
تفاوت این دو در هزینه هم دیده میشود
نگهداشتن یک کامپوننت پنهان در درخت، به معنای این است که Effectهای آن همچنان (بسته به Dependency Arrayشان) فعال میمانند و منابعی که مصرف میکند، آزاد نمیشوند. برای کامپوننتهای سنگین یا نادر، این میتواند هزینهای باشد که باید در نظر گرفت؛ در مقابل حذف کامل، هزینه از دست رفتن State و اجرای دوباره منطق اولیه را دارد.
مثال قابل اجرا
در این مثال، هر دو روش کنار هم قرار دارند. یک متن در هرکدام بنویسید، دکمه مربوط به آن را بزنید و تفاوت را ببینید.
جمعبندی
حذف کامل یک عنصر از خروجی JSX باعث Unmount و از بین رفتن State آن میشود؛ پنهان کردن ظاهری با CSS، کامپوننت را در درخت نگه میدارد و State آن حفظ میشود. انتخاب بین این دو، به این بستگی دارد که آیا بازگشت بعدی باید «ادامه همان حالت قبلی» باشد یا «شروعی تازه». در درس بعدی، اثر تغییر ساختار درخت را روی این رفتار بررسی میکنیم.
