چه زمانی نباید از Effect استفاده کرد

در طول این فصل، بارها دیدیم Effect چه کاری انجام می‌دهد و چگونه باید نوشته شود. اما به همان اندازه مهم است بدانیم چه زمانی اصلاً نباید از Effect استفاده کرد. استفاده نابه‌جا از Effect، یکی از رایج‌ترین دلایل کدهای پیچیده و پر از اشکال در برنامه‌های React است.

قاعده کلی: Effect آخرین گزینه است، نه اولین

یک عادت ذهنی مفید این است: پیش از نوشتن یک useEffect، از خودتان بپرسید آیا واقعاً به همگام‌سازی با چیزی خارج از React نیاز دارید؟ اگر پاسخ منفی است، احتمالاً Effect ابزار درستی برای آن مسئله نیست.

مورد اول: محاسبه یک مقدار از روی State یا Props موجود

همان‌طور که در فصل سوم، در درس Derived State دیدیم، اگر مقداری را می‌توان مستقیماً از روی داده فعلی محاسبه کرد، نباید آن را در یک State جداگانه که با Effect به‌روزرسانی می‌شود نگه داشت:

// نادرست
function Cart({ items }) {
  const [total, setTotal] = useState(0);

  useEffect(() => {
    setTotal(items.reduce((sum, item) => sum + item.price, 0));
  }, [items]);

  return <p>{total}</p>;
}

// درست
function Cart({ items }) {
  const total = items.reduce((sum, item) => sum + item.price, 0);
  return <p>{total}</p>;
}

مورد دوم: واکنش به رویداد کاربر

همان‌طور که در درس Synchronizing with External Systems دیدیم، کاری که باید دقیقاً به‌خاطر یک تعامل خاص کاربر اجرا شود (کلیک، ارسال فرم، تغییر یک انتخاب)، باید مستقیماً در Event Handler همان تعامل نوشته شود، نه در یک Effect که به تغییر State واکنش نشان می‌دهد.

// نادرست
useEffect(() => {
  if (justSubmitted) {
    showToast("فرم با موفقیت ارسال شد");
  }
}, [justSubmitted]);

// درست
function handleSubmit() {
  saveForm();
  showToast("فرم با موفقیت ارسال شد");
}

مورد سوم: به‌روزرسانی یک State بر اساس تغییر State دیگر

گاهی توسعه‌دهندگان برای هماهنگ نگه‌داشتن دو State مرتبط، از یک Effect استفاده می‌کنند که با تغییر State اول، State دوم را به‌روزرسانی می‌کند. اما در بسیاری از این موارد، بهتر است این هماهنگی مستقیماً در همان Event Handلری که باعث تغییر اول شده، انجام شود:

// نادرست
useEffect(() => {
  setFullName(firstName + " " + lastName);
}, [firstName, lastName]);

// درست: fullName اصلاً نیازی به State جداگانه ندارد
const fullName = firstName + " " + lastName;

مورد چهارم: بازنشانی State هنگام تغییر یک Prop خاص

الگوی دیگری که گاهی به‌اشتباه با Effect پیاده‌سازی می‌شود، بازنشانی یک State داخلی هر بار که یک Prop خاص تغییر می‌کند (مثلاً پاک کردن فیلد جست‌وجو با تغییر کاربر انتخاب‌شده). راه‌حل بهتر برای این موقعیت، معمولاً استفاده از key روی کامپوننت است، نه یک Effect؛ موضوعی که با جزئیات کامل در فصل دوازدهم، درباره حفظ و بازنشانی State، بررسی خواهیم کرد.

یک معیار ساده برای تشخیص

اگر بتوانید جمله «این کامپوننت باید با X همگام بماند» را برای یک منطق بنویسید و آن X واقعاً چیزی خارج از React باشد (سرور، تایمر، یک سرویس مرورگر)، احتمالاً Effect مناسب است. اگر منطق شما با جمله‌هایی مانند «وقتی X تغییر کرد، Y را محاسبه کن» یا «وقتی کاربر کلیک کرد، Z را انجام بده» بهتر توصیف می‌شود، احتمالاً به Effect نیازی ندارید.

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

محاسبه مستقیم به‌جای Effect غیرضروری
برای دیدن پیش‌نمایش کامپوننت، روی Run بزنید.

جمع‌بندی

Effect نباید برای محاسبه مقادیر قابل‌اشتقاق، واکنش به رویدادهای کاربر، یا هماهنگ نگه‌داشتن دو State مرتبط استفاده شود؛ این موارد معمولاً با محاسبه مستقیم یا منطق داخل Event Handler بهتر حل می‌شوند. Effect را برای زمانی نگه دارید که واقعاً باید با چیزی خارج از React همگام بمانید. با این درس، فصل ششم به پایان می‌رسد و در ادامه به آزمون فصل ۶ می‌رویم.