State Reset: چگونه عمداً State یک کامپوننت را بازنشانی کنیم

در درس قبل دیدیم React به‌طور پیش‌فرض State را حفظ می‌کند. اما گاهی دقیقاً برعکس این رفتار را می‌خواهیم: می‌خواهیم مطمئن شویم یک کامپوننت، در شرایط خاصی، کاملاً از صفر شروع شود. در این درس، روش‌های رایج برای این کار را با هم می‌بینیم.

روش اول: تغییر key

همان‌طور که در درس دوم این فصل دیدیم، دادن یک key که به مقداری خاص وابسته است، ساده‌ترین و رایج‌ترین راه برای اجبار به بازنشانی است:

<ProfileForm key={userId} userId={userId} />

این روش برای مواردی مثل تغییر کاربر، تغییر آیتم انتخاب‌شده در یک لیست، یا هر موقعیتی که یک مقدار مشخص، «شناسه» مفهومی یک نمونه تازه باشد، مناسب‌ترین گزینه است.

روش دوم: تغییر key روی یک والد بی‌نام

گاهی می‌خواهیم کل یک بخش از رابط کاربری، همراه با تمام State داخلی‌اش (نه فقط یک کامپوننت خاص)، بازنشانی شود. در این حالت، می‌توان key را روی یک عنصر بیرونی‌تر گذاشت:

function Wizard({ step }) {
  return (
    <div key={step}>
      <StepForm />
      <StepNotes />
    </div>
  );
}

با تغییر step، کل div و همه فرزندانش (هم StepForm و هم StepNotes) یک هویت جدید پیدا می‌کنند و از نو ساخته می‌شوند؛ دقیقاً مناسب زمانی که چند مرحله ویزارد باید کاملاً مستقل از هم باشند.

روش سوم: تغییر ساختار اطراف با شرط

همان‌طور که در درس اول این فصل دیدیم، اگر نوع یا موقعیت یک کامپوننت عوض شود، هویت آن هم عوض می‌شود. گاهی می‌توان از همین رفتار طبیعی برای بازنشانی استفاده کرد؛ مثلاً با قرار دادن یک کامپوننت در دو شاخه واقعاً متفاوت درخت:

function Page({ mode }) {
  return mode === "edit" ? (
    <div><EditForm /></div>
  ) : (
    <section><EditForm /></section>
  );
}

چون والد بین div و section عوض شده، موقعیت واقعی EditForm در درخت فرق می‌کند و React آن را نمونه تازه‌ای در نظر می‌گیرد. این روش کمتر رایج است و معمولاً بهتر است آگاهانه و با استفاده از key انجام شود، نه به‌طور تصادفی از تغییر ساختار.

روش چهارم: خواندن مقدار اولیه با یک Effect

اگر نخواهیم کل کامپوننت از نو Mount شود (مثلاً چون Refهای متصل به DOM باید باقی بمانند)، می‌توان با یک Effect که به مقدار موردنظر وابسته است، State را به‌صورت دستی بازنشانی کرد:

function CommentBox({ postId }) {
  const [text, setText] = useState("");

  useEffect(() => {
    setText("");
  }, [postId]);

  return <textarea value={text} onChange={(e) => setText(e.target.value)} />;
}

این روش کار می‌کند، اما یک رندر اضافه ایجاد می‌کند: ابتدا کامپوننت با مقدار قدیمی رندر می‌شود، سپس Effect اجرا و State پاک می‌شود. به همین دلیل، در اکثر موارد، روش key ساده‌تر و کاراتر است؛ این روش بیشتر برای مواقعی مناسب است که فقط بخشی از State باید بازنشانی شود، نه کل کامپوننت.

کدام روش را انتخاب کنیم

قاعده کلی: اگر می‌خواهید یک کامپوننت کاملاً از نو (با Mount تازه و اجرای دوباره Effectهای اولیه‌اش) شروع شود، از key استفاده کنید. اگر فقط یک فیلد خاص از State باید پاک شود، در حالی که بقیه کامپوننت (و مثلاً فوکوس آن) دست‌نخورده بماند، استفاده از یک Effect هدفمند مناسب‌تر است.

مثال قابل اجرا

بازنشانی کامل یک فرم با تغییر key
برای دیدن پیش‌نمایش کامپوننت، روی Run بزنید.

جمع‌بندی

برای بازنشانی عمدی State، رایج‌ترین راه تغییر key روی همان کامپوننت یا یک والد بیرونی‌تر است؛ روش دیگر، استفاده از یک Effect هدفمند برای پاک کردن فقط بخشی از State، بدون Mount تازه کل کامپوننت. انتخاب بین این دو به این بستگی دارد که آیا می‌خواهیم کل کامپوننت از نو ساخته شود یا فقط یک مقدار خاص پاک شود. در درس بعدی به رابطه Conditional Rendering و State می‌پردازیم.