ویرگول
ورودثبت نام
Ahmad Safari
Ahmad Safari
Ahmad Safari
Ahmad Safari
خواندن ۷ دقیقه·۲ ماه پیش

ری اکت پشت صحنه چطور رویکرد Declarative رو هندل می‌کنه

برای اینکه بفهمیم React پشت صحنه چطور رویکرد Declarative رو هندل میکنه، باید به نحوه کار داخلی React و مکانیزمهایی که برای مدیریت رندرینگ و آپدیت DOM استفاده میکنه نگاه کنیم. تو این پاسخ، من این فرآیند رو به زبون ساده و با جزئیات توضیح میدم و قدم به قدم نشون میدم که React چطور از کد Declarative (توصیفی) شما به آپدیتهای بهینه DOM میرسه. همچنین یه مثال عملی میذارم تا موضوع روشنتر بشه.


چطور React رویکرد Declarative رو مدیریت میکنه؟

وقتی تو React یه UI رو به صورت Declarative مینویسی (مثلاً با JSX و state)، شما فقط توصیف میکنی که UI باید چه شکلی باشه، و React پشت صحنه مسئولیت تبدیل این توصیف به تغییرات واقعی تو DOM رو بر عهده میگیره. این فرآیند چند مرحله کلیدی داره:

  1. JSX به JavaScript ترجمه میشه:

    • JSX (که شبیه HTMLه) در واقع یه syntax sugar برای فراخوانی تابع React.createElementه. وقتی کد JSX مینویسی، کامپایلر (مثل Babel) اون رو به یه ساختار داده JavaScript به اسم React Element تبدیل میکنه.

    • React Element یه شیء سبک (lightweight)ه که توصیف میکنه یه کامپوننت یا عنصر DOM باید چه شکلی باشه (مثلاً نوع تگ، props، و فرزندانش).

    // JSX

    <div className="container">سلام دنیا</div>

    // تبدیل به:

    React.createElement('div', { className: 'container' }, 'سلام دنیا');

    این شیء یه tree از React Elementها میسازه که بهش میگیم Virtual DOM.

  2. Virtual DOM و رندرینگ اولیه:

    • Virtual DOM یه نسخه سبک و در حافظه (in-memory) از DOM واقعیه که React ازش برای مدیریت UI استفاده میکنه.

    • وقتی کامپوننت رندر میشه (مثلاً با render یا createRoot)، React یه tree از React Elementها (Virtual DOM) میسازه که توصیف کاملی از UI بر اساس state و props فعلیه.

    • تو رندر اولیه، React این Virtual DOM رو به DOM واقعی (real DOM) تبدیل میکنه و عناصر رو تو صفحه نمایش میده.

  3. Reconciliation (همگامسازی):

    • وقتی state یا props تغییر میکنه، React یه Virtual DOM جدید میسازه که UI رو با state/propهای جدید توصیف میکنه.

    • حالا React این Virtual DOM جدید رو با Virtual DOM قبلی مقایسه میکنه (به این فرآیند میگن Diffing). این مقایسه خیلی بهینهست، چون React از یه الگوریتم خاص (heuristic-based diffing) استفاده میکنه که فقط بخشهای تغییرکرده رو شناسایی میکنه.

    • بعد از پیدا کردن تغییرات، React فقط بخشهای لازم از DOM واقعی رو آپدیت میکنه (به این میگن Reconciliation).

  4. بهینهسازی با Diffing:

    • الگوریتم Diffing در React خیلی سریع عمل میکنه، چون:

      • فقط کامپوننتهایی که props یا stateشون تغییر کرده رو دوباره رندر میکنه.

      • از کلیدهای منحصربهفرد (key) تو لیستها استفاده میکنه تا تغییرات رو دقیقتر تشخیص بده.

      • به جای بازنویسی کل DOM، فقط عملیاتهای ضروری (مثل تغییر متن، اضافه/حذف عنصر، یا آپدیت ویژگیها) رو انجام میده.

  5. Batch Updates (بهروزرسانیهای دستهای):

    • تو React 18، آپدیتهای state به صورت خودکار دستهبندی (batch) میشن. یعنی اگه چند setState پشت سر هم فراخوانی بشن، React همه تغییرات رو جمع میکنه و فقط یه بار رندر میکنه تا عملکرد بهینه بمونه.

  6. Concurrent Rendering (در React 18):

    • با معرفی createRoot و قابلیتهای Concurrent Rendering، React میتونه رندرینگ رو به صورت قابل وقفه (interruptible) انجام بده. مثلاً اگه یه آپدیت سنگین در جریان باشه و کاربر یه تعامل فوری (مثل تایپ) انجام بده، React میتونه رندر سنگین رو متوقف کنه و به تعامل کاربر اولویت بده.


فرآیند قدم به قدم پشت صحنه

بیایم با یه مثال ساده فرآیند رو مرحله به مرحله بررسی کنیم:

کد نمونه (Declarative):

import { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); return ( <div> <p>شمارنده: {count}</p> <button ={() => setCount(count + 1)}>اضافه کن</button> </div> }


چطور React این کد رو هندل میکنه؟

  1. تبدیل JSX به React Elementها:

    • وقتی کامپوننت Counter رندر میشه، JSX به یه ساختار JavaScript تبدیل میشه:

      React.createElement('div', null,

      React.createElement('p', null, شمارنده: ${count}),

      React.createElement('button', { : () => setCount(count + 1) }, 'اضافه کن')

      این یه tree از React Elementها میسازه که Virtual DOM اولیه رو تشکیل میده.

  2. رندر اولیه:

  3. React این Virtual DOM رو به DOM واقعی تبدیل میکنه و عناصر <div>, <p>, و <button> رو تو صفحه قرار میده.

<p>شمارنده: 0</p> <button>اضافه کن</button> </div>
  1. تغییر State (کلیک روی دکمه):

    • وقتی کاربر روی دکمه کلیک میکنه، setCount(count + 1) فراخوانی میشه و count به 1 تغییر میکنه.

    • React دوباره کامپوننت رو رندر میکنه (به صورت داخلی) و یه Virtual DOM جدید میسازه:

      React.createElement('div', null,

      React.createElement('p', null, شمارنده: 1),

      React.createElement('button', { : () => setCount(count + 1) }, 'اضافه کن')

    • Diffing و Reconciliation:

      • React Virtual DOM جدید رو با قبلی مقایسه میکنه:

        • میبینه که <div> و <button> هیچ تغییری نکردن (props و ساختار همونه).

        • فقط متن داخل <p> از شمارنده: 0 به شمارنده: 1 تغییر کرده.

      • React فقط متن داخل <p> رو تو DOM واقعی آپدیت میکنه (مثلاً با textContent) و بقیه DOM رو دست نمیزنه.

    • نتیجه در DOM:

      • DOM واقعی به این شکل آپدیت میشه:

    <div> <p>شمارنده: 1</p> <button>اضافه کن</button> </div>


    جزئیات فنیتر پشت صحنه

    1. Fiber Architecture:

      • از React 16 به بعد، React از یه معماری داخلی به اسم Fiber استفاده میکنه. Fiber یه ساختار دادهست که به React اجازه میده رندرینگ رو به واحدهای کوچکتر (fiber nodes) تقسیم کنه.

      • این معماری به React امکان میده:

        • رندرینگ رو متوقف کنه یا ادامه بده (برای Concurrent Rendering).

        • اولویتبندی کنه (مثلاً تعاملات کاربر اولویت بالاتری دارن).

        • تغییرات رو به صورت incremental اعمال کنه.

    2. Scheduler:

      • React از یه ماژول داخلی به اسم Scheduler (معرفیشده تو React 18) استفاده میکنه تا وظایف رندرینگ رو زمانبندی کنه.

      • مثلاً اگه یه آپدیت سنگین (مثل رندر یه لیست بزرگ) در جریان باشه، Scheduler میتونه اون رو به تعویق بندازه تا یه آپدیت فوری (مثل پاسخ به کلیک کاربر) انجام بشه.

    3. Batching خودکار:

      • تو React 18، آپدیتهای state که تو یه رویداد (مثل کلیک) رخ میدن، به صورت خودکار دستهبندی میشن. این یعنی React فقط یه بار رندر میکنه، حتی اگه چندین setState فراخوانی بشه.

    4. مدیریت رویدادها (Synthetic Events):

      • React یه سیستم رویداد مصنوعی (Synthetic Event) داره که رویدادهای DOM (مثل ) رو مدیریت میکنه. این سیستم به React اجازه میده رویدادها رو بهینهتر پردازش کنه و با state هماهنگ باشه.


    مثال پیشرفتهتر: لیست فیلترشده

    برای نشون دادن اینکه React چطور Declarative رو تو سناریوهای پیچیدهتر مدیریت میکنه، بیایم یه مثال از یه لیست فیلترشده رو بررسی کنیم:

import { useState } from 'react'; function FilterList() { const [filter, setFilter] = useState(''); const items = ['سیب', 'موز', 'پرتقال', 'انگور']; const filteredItems = items.filter((item) => item.includes(filter)); return ( <div> <input type="text" value={filter} ={(e) => setFilter(e.target.value)} placeholder="فیلتر..." /> <ul> {filteredItems.map((item) => ( <li key={item}>{item}</li> ))} </ul> </div> ); }


پشت صحنه چه اتفاقی میافته؟

  1. رندر اولیه:

    • JSX به یه Virtual DOM تبدیل میشه که شامل یه <div>, یه <input>, و یه <ul> با تمام آیتمهای itemsه.

    • React این Virtual DOM رو به DOM واقعی تبدیل میکنه.

  2. تغییر State (تایپ تو اینپوت):

    • وقتی کاربر تو اینپوت تایپ میکنه (مثلاً "سیب")، setFilter فراخوانی میشه و filter به "سیب" آپدیت میشه.

    • React یه Virtual DOM جدید میسازه که فقط شامل <li>هایی میشه که با "سیب" همخونی دارن (مثلاً فقط <li>سیب</li>).

  3. Diffing:

    • React Virtual DOM جدید رو با قبلی مقایسه میکنه:

      • میبینه که <input> تغییر کرده (مقدارش از "" به "سیب").

      • میبینه که <ul> تغییر کرده، چون حالا فقط یه <li> داره (به جای 4 تا).

    • React از keyها (مثل key={item}) استفاده میکنه تا بفهمه کدوم <li>ها حذف شدن و کدوما موندن.

  4. آپدیت DOM:

    • React فقط این تغییرات رو اعمال میکنه:

      • مقدار value اینپوت رو به "سیب" آپدیت میکنه.

      • سه <li> (موز، پرتقال، انگور) رو از <ul> حذف میکنه.

    • این کار خیلی بهینهست، چون React کل <ul> رو از نو نمیسازه، فقط آیتمهای غیرضروری رو حذف میکنه.

  5. Concurrent Rendering (در React 18):

    • اگه لیست خیلی بزرگ باشه (مثلاً 10,000 آیتم)، React میتونه رندرینگ <ul> رو به تکههای کوچکتر تقسیم کنه و اگه کاربر همزمان تایپ کنه، رندرینگ رو متوقف کنه تا اینپوت پاسخگو بمونه.


چرا این رویکرد Declarative بهینهست؟

  1. مدیریت خودکار DOM:

    • شما نیازی نداری نگران جزئیات آپدیت DOM باشی (مثل پیدا کردن عنصر یا حذف دستی). React این کار رو بهینه انجام میده.

  2. عملکرد بالا:

    • Virtual DOM و الگوریتم Diffing باعث میشن فقط تغییرات لازم اعمال بشن، نه کل DOM.

  3. خوانایی و نگهداری:

    • چون شما فقط UI رو توصیف میکنی، کد تمیزتر و قابلفهمتره.

  4. پشتیبانی از قابلیتهای پیشرفته:

    • معماری Fiber و Concurrent Rendering به React اجازه میدن رندرها رو به صورت هوشمند و غیرهمزمان مدیریت کنه، که برای اپهای پیچیده عالیه.


جمعبندی

React رویکرد Declarative رو با این مکانیزمها مدیریت میکنه:

  • JSX به React Elementها: کد توصیفی شما به یه ساختار داده سبک (Virtual DOM) تبدیل میشه.

  • Virtual DOM و Diffing: React تغییرات رو با مقایسه Virtual DOM جدید و قدیم شناسایی میکنه.

  • Reconciliation: فقط بخشهای لازم DOM واقعی آپدیت میشن.

  • Fiber و Scheduler: رندرینگ بهینه و قابل وقفه میشه، مخصوصاً تو React 18.

  • Batching و Synthetic Events: آپدیتها و رویدادها به صورت خودکار بهینهسازی میشن.

gt ltvirtual domreact
۰
۰
Ahmad Safari
Ahmad Safari
شاید از این پست‌ها خوشتان بیاید