درود دوستان 👋 می‌خوایم دو هوک ری‌اکتی رو با هم مقایسه کنیم که توی اسم و ظاهر خیلی شبیه به هم هستن. اما کاربرهای منحصر به فردی دارن. این پست از مجموعه پست‌های ری‌اکت ۱۰۱ هست که شامل مجموعه‌ای از پست‌های کوتاه و کاربردی ری‌اکتی میشه.

 

useEffect چیه؟

این هوک که احتمالاً خیلی بیشتر با اون آشنایی دارین، برای مدیریت Side Effect ها توی یک کامپوننت ری‌اکت به کار میره. منظور از Side Effect اتفاق‌هایی هست که می‌خوایم بعد از رخ دادن یک رویداد توی کامپوننت انجام بشه. مثلاً وقتی که مقدار یک استیت بروز میشه، یا وقتی که کامپوننت برای اولین بار رندر میشه و می‌خوایم API Call انجام بدیم. احتمالاً با نحوهٔ پیاده‌سازی این هوک آشنایی دارین، بنابراین از این قسمت صرف نظر کنیم.

 

useLayoutEffect چیه؟

این هوک یک هوک خاص توی ری‌اکت هست و کاربردهای محدودتر و منحصر به فردی داره؛ گرچه این هوک هم مثل useEffect برای مدیریت کردن Side Effect ها به کار میره و نحوهٔ پیاده‌سازی مشابهی داره:

useLayoutEffect(() => {
  // Do Side Effects
}, []);

همون‌طور که می‌بینیم این هوک هم یک کال‌بک و یک آرایه برای تعریف Dependency ها می‌گیره. چیزی که این دو هوک رو از هم متمایز می‌کنه، نحوه و زمان اجرای اون کال‌بکی هست که تعریف کردیم.

 

تفاوت‌های این دو هوک

وقتی تغییری توی DOM رخ میده، بعد از اون، مرحله‌ای وجود داره به اسم Painting مرورگر که مرورگر باید تغییرات رو توی صفحه نمایش بده. به عبارت دیگه، منظور از Painting مرورگر، زمانی هست که تغییری توی DOM صورت گرفته و مرورگر می‌خواد اون تغییرات رو نشون بده. به این عملیات گفته میشه Painting.

 

تفاوت اول

اولین تفاوت مهم این دو هوک اینه که توی useLayoutEffect کال‌بک مد نظر ما بعد از تغییر توی DOM و از عملیات Painting اجرا میشه. در صورتی که useEffect کار مد نظر ما  از عملیات Painting اجرا می‌کنه.

 

تفاوت دوم

دومین تفاوت مهم اینه که useLayoutEffect کال‌بک ما رو به صورت Synchronous اجرا می‌کنه و بنابراین Render Blocking هست و تا زمانی که اجرای اون کال‌بک تموم نشده عملیات بعدی از جمله Painting مرورگر قابل اجرا شدن نیستن. بر خلاف useEffect که اجرای کال‌بک اون Async هست و باعث بلاک شدن کامپوننت نمیشه.

کد زیر یک نمونه از زمانی هست که این هوک باعث بلاک شدن کامپوننت میشه:

export default function App() {
  const [count, setCount] = useState(0);

  useLayoutEffect(() => {
    const now = performance.now();
    while (performance.now() - now < 2000) {} 
  });

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={() => setCount((prev) => prev + 1)}>Increment</button>
    </div>
  );
}

توی کد خروجی بالا وقتی که روی دکمه کلیک می‌کنیم همونطور که می‌بینیم مرورگر به مدت ۲ ثانیه فریز میشه و سپس تغییرات رو برای ما نمایش میده. پس باید دقت کنیم که جز در موارد ضروری که توی ادامه بررسی میشه از این هوک استفاده نکنیم.

 

چه زمانی useLayoutEffect به کارمون میاد؟

همونطور که گفتیم این هوک زمانی اجرا میشه که تغییری توی DOM صورت گرفته اما مرورگر هنوز تغییرات رو اعمال نکرده. به عبارت دیگه قبل از عملیات Painting اجرا میشه. با توجه به این قضیه، استفاده از این هوک رو زمانی باید ترجیح بدیم که واقعاً می‌خوایم کاری انجام بدیم که وابسته به UI هست و لازم داریم اون رو قبل از عملیات Painting انجام بدیم (زمانی که مرورگر هنوز تغییرات جدید رو اعمال نکرده.) در غیر این صورت برای انجام Side Effect ها می‌بایست در اکثر موارد useEffect رو به دلیل اینکه Async هست و باعث بلاک شدن مرورگر نمیشه ترجیح بدیم.

 

خب دوستان این پست هم به پایان رسید. امیدوارم از اطلاعاتی که بررسی کردیم استفاده کرده باشین. تا یه پست دیگه خدانگهدار 😉✌️

https://kentcdodds.com/blog/useeffect-vs-uselayouteffect