تحلیل کامل جریان یک به‌روزرسانی، از رویداد تا صفحه

در این فصل، هر بخش از فرایند رندرینگ را جداگانه دیدیم: Render و Commit، Component Tree، Reconciliation، نقش Key، و دلایل Re-render. در این درس آخر فصل، همه این قطعات را در قالب یک جریان واحد و پیوسته کنار هم می‌گذاریم تا تصویر کامل شکل بگیرد.

یک مثال کامل برای دنبال کردن

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

  return (
    <div>
      <p>عدد: {count}</p>
      <button onClick={() => setCount(count + 1)}>افزایش</button>
      <Footer />
    </div>
  );
}

function Footer() {
  return <p>پایین صفحه</p>;
}

حالا فرض کنید کاربر روی دکمه کلیک می‌کند. بیایید قدم‌به‌قدم دنبال کنیم چه اتفاقی می‌افتد.

قدم اول: رویداد و درخواست به‌روزرسانی

کلیک باعث اجرای Event Handler می‌شود و setCount(count + 1) فراخوانی می‌شود. این فراخوانی، همان‌طور که در فصل سوم دیدیم، بلافاصله چیزی را تغییر نمی‌دهد؛ فقط به React اعلام می‌کند که App باید دوباره Render شود.

قدم دوم: Render Phase

React تابع App را دوباره اجرا می‌کند. چون App رندر می‌شود، طبق چیزی که در درس قبل دیدیم، کل زیردرخت آن هم دوباره محاسبه می‌شود؛ یعنی Footer هم دوباره اجرا می‌شود، حتی با اینکه هیچ Propی نمی‌گیرد و خروجی‌اش تغییری نکرده است.

قدم سوم: Reconciliation

React خروجی جدید (درخت عناصر) را با خروجی رندر قبلی مقایسه می‌کند. طبق قاعده‌ای که در درس چهارم دیدیم، نوع و موقعیت هر عنصر بررسی می‌شود: div، p، button و Footer، همگی در همان موقعیت و با همان نوع قبلی هستند. React تشخیص می‌دهد فقط متن داخل اولین p از "عدد: 0" به "عدد: 1" تغییر کرده است.

قدم چهارم: Commit Phase

React فقط همان یک تفاوت را در DOM واقعی اعمال می‌کند: به‌روزرسانی متن یک گره متنی. عناصر div، button و محتوای Footer، هرچند دوباره محاسبه شده بودند، چون هیچ تفاوتی نداشتند، در DOM واقعی دست‌نخورده باقی می‌مانند.

خلاصه جریان کامل

کلیک روی دکمه
   ↓
فراخوانی setCount (درخواست به‌روزرسانی)
   ↓
Render Phase: اجرای دوباره App و Footer (محاسبه، نه تغییر واقعی)
   ↓
Reconciliation: مقایسه درخت جدید و قدیم بر اساس نوع و موقعیت
   ↓
Commit Phase: فقط تغییر متن در DOM واقعی اعمال می‌شود
   ↓
اجرای Effectهای وابسته (در صورت وجود)

چرا این جریان اهمیت دارد

این تحلیل نشان می‌دهد که «رندر شدن دوباره یک تابع» و «تغییر واقعی روی صفحه» دو چیز کاملاً متفاوت‌اند. Footer بدون هیچ تغییر Propی، دوباره اجرا شد، اما هیچ اثری روی DOM واقعی نداشت. همین جداسازی است که در فصل سیزدهم، پایه بحث بهینه‌سازی و ابزارهایی مانند React.memo خواهد بود؛ ابزاری که هدفش جلوگیری از همان محاسبه اضافه در Render Phase است، نه چیزی درباره Commit.

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

کنسول را باز کنید و روی دکمه کلیک کنید تا ببینید Footer با هر کلیک دوباره اجرا می‌شود، در حالی که ظاهرش هرگز تغییر نمی‌کند.

مشاهده کامل جریان Render تا Commit
برای دیدن پیش‌نمایش کامپوننت، روی Run بزنید.

جمع‌بندی

یک به‌روزرسانی معمولی این مسیر را طی می‌کند: رویداد باعث درخواست تغییر State می‌شود؛ React در Render Phase، کامپوننت و زیردرخت آن را دوباره محاسبه می‌کند؛ در Reconciliation، این خروجی جدید با نسخه قبلی مقایسه می‌شود؛ و در Commit Phase، فقط تفاوت واقعی روی DOM اعمال می‌شود. با این درس، فصل یازدهم به پایان می‌رسد و در ادامه به آزمون فصل ۱۱ می‌رویم.