Re-render و Performance: از کجا شروع کنیم

در فصل یازدهم با دلایل Re-render و جریان Render تا Commit آشنا شدیم. در این فصل، به سراغ بهینه‌سازی می‌رویم: چه زمانی Re-renderهای زیاد واقعاً مشکل‌ساز می‌شوند و چه زمانی نگرانی درباره آن‌ها بیهوده است. این درس اول، چارچوب کلی فکر کردن درباره Performance در React را می‌سازد.

Re-render گران نیست، همیشه

یک باور اشتباه رایج این است که هر Re-render، خودش یک مشکل عملکردی است. اما همان‌طور که در فصل یازدهم دیدیم، Render Phase فقط یک محاسبه جاوااسکریپتی است و Commit Phase فقط تفاوت واقعی را در DOM اعمال می‌کند. برای اکثر کامپوننت‌های ساده، این محاسبه به‌قدری سریع است که کاربر هیچ تأخیری حس نمی‌کند؛ حتی اگر کامپوننتی چند بار بیشتر از حد لازم Render شود.

پس چه زمانی واقعاً مشکل می‌شود

Re-render وقتی به یک مشکل واقعی تبدیل می‌شود که یکی از این شرایط برقرار باشد:

  • کامپوننت محاسبه سنگینی در بدنه خودش انجام می‌دهد (مثلاً پردازش روی هزاران آیتم)، و این محاسبه با هر Render دوباره تکرار می‌شود.
  • تعداد زیادی کامپوننت فرزند، در یک زیردرخت بزرگ، با هر تغییر کوچک، به‌طور غیرضروری دوباره Render می‌شوند.
  • یک State با فرکانس بسیار بالا تغییر می‌کند (مثلاً موقعیت اسکرول یا موس) و باعث Re-render مکرر بخش بزرگی از برنامه می‌شود.

قاعده اول: اول اندازه بگیرید، بعد بهینه کنید

پیش از هر اقدام بهینه‌سازی، باید بدانیم مشکل واقعاً کجاست. حدس زدن این‌که «این کامپوننت احتمالاً کند است»، اغلب اشتباه از آب درمی‌آید. ابزار React DevTools، که در درس آخر همین فصل بررسی می‌شود، دقیقاً برای همین اندازه‌گیری طراحی شده است: نشان می‌دهد کدام کامپوننت‌ها چند بار و چرا Render شده‌اند.

قاعده دوم: بهینه‌سازی زودهنگام، هزینه خودش را دارد

ابزارهایی که در درس‌های بعدی می‌بینیم، مثل React.memo، useMemo و useCallback، رایگان نیستند؛ هرکدام کمی پیچیدگی به کد اضافه می‌کنند و خودشان هم هزینه محاسباتی کوچکی دارند (مثلاً مقایسه Propهای قبلی و جدید). استفاده از این ابزارها در جایی که هیچ مشکل واقعی وجود ندارد، معمولاً کد را پیچیده‌تر می‌کند بدون اینکه سود محسوسی بدهد.

ترتیب درست فکر کردن

یک ترتیب منطقی برای برخورد با یک مشکل عملکردی احتمالی:

  1. آیا کاربر واقعاً کندی را حس می‌کند؟ (نه فرض ذهنی ما)
  2. با ابزار اندازه‌گیری، کدام کامپوننت مسئول این کندی است؟
  3. آیا مشکل از محاسبه سنگین است، از تعداد زیاد Re-render فرزندان، یا از هر دو؟
  4. بر اساس این تشخیص، ابزار مناسب (memo، useMemo، useCallback یا بازطراحی ساختار) را انتخاب کنید.

در درس‌های بعدی این فصل، هرکدام از این ابزارها را با جزئیات کامل بررسی می‌کنیم.

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

در این مثال، یک کامپوننت فرزند ساده با هر کلیک دوباره Render می‌شود، اما چون کارش سبک است، هیچ تأخیری حس نمی‌شود؛ کنسول را باز کنید تا این Renderهای بی‌ضرر را ببینید.

Re-render سبک، بدون تأثیر محسوس بر عملکرد
برای دیدن پیش‌نمایش کامپوننت، روی Run بزنید.

جمع‌بندی

اکثر Re-renderها بی‌ضرر و سریع هستند و نیازی به بهینه‌سازی ندارند. مشکل واقعی معمولاً از محاسبات سنگین، زیردرخت‌های بزرگ، یا Stateهای با فرکانس بالا می‌آید. پیش از استفاده از ابزارهای بهینه‌سازی، باید ابتدا با اندازه‌گیری واقعی، محل مشکل را پیدا کرد. در درس بعدی، به سراغ اولین ابزار می‌رویم: React.memo.