آپدیت جدید ری اکت(React) به نسخه 18 ، آیا آپدیت بزرگی در راه است ؟


بعد از آپدیت ری اکت به نسخه 17 و اضافه نشدن هیچ قابلیت جدیدی به ری اکت 17 بسیاری از توسعه دهندگان این لایبرری جذاب رو مایوس کرد ! اونا فقط جز چنتا ایمپرومنت ویژگی جدیدی رو از ری اکت 17 ندیدن ! بد تر از همه این بود که ری اکت 17 بعد از دو سال و نیم که از ریلیز شدن نسخه 16 و اضافه شدن ویژگی های جذاب هوک میگذشت ، ریلیز شد و حسابی باعث کلافه شدن دولوپرای ری اکت شد ! از طرفی نکست جی اس هم که خودش رو به یک فریم ورک تمام عیار تبدیل کرده بود این یاس رو تشدید میکرد !

دولوپرای ری اکت میدیدن که هروز یه ایمپرومنت جدید برای نکست میاد ، توبیاس کوپرز (فوندر وب پک ) به تیم نکست اضافه میشه ! کلی ایمپرومنت جدید برای نمایش عکس و فونت و سئو دارند ! کم کم اونایی که مجاب نشده بودند تا الان رو هم مجاب به این کوچ پر هزینه کرد ! و اما برگ برنده ری اکت برای خاموش شدن اینهمه اعتقاد قبل از کریسمس اتفاق افتاد و اونا با رسانه ای کردن قابلیت server component که چیزی شبیه به ssr با قابلیت کئوری مستقیم روی دیتابیس بود رو اعلام کردند و اجرایی کردنش رو به بعد کریسمس موکول کردند ! این قضیه تا حد زیادی آب روی آتیشی بود که تونست دولوپرای ری اکت راضی نگه داره !

حدود یک ماه پیش نکست جی اس اعلام کرد که قراره کنفرانسی رو به رسم عادت سال گذشته اش به همراه تیم گوگل برگزار کنه و این کنفرانس 15 June برگزار میشه و قبلش باید از داخل سایتش تیکت بگیرید تا بهتون اجازه حضور در جلسه شونو بده ! درست 3 روز قبل از این اتفاق یعنی درست امروز 12 june ، ری اکت خیلی بی سر صدا از لانچ شدن نسخه 18 آلفای ری اکت پرده برداشت ! اونا اعلام کردند که خیلی تغییرات اساسی رو توی کدبیس ری اکت دادن و قراره خیلی تغییرات و ایمپرومنت های باحالی براش تو ماه آینده بیاد !

اونا اینشکلی زمان بندی لانچ نسخه 18 رو اعلام کردند :


زمانی لانچ ری اکت نسخه 18

در نهایت چیزی که مشخصه میتونیم تا اخر سال میلادی امسال ری اکت 18 نسخه نهایی رو داشته باشیم !

ری اکت اعلام کرد که برای ادامه کار یه سری گروه های کاری تشکیل داده که دولوپرا میتونن باهم دیگه راجب نسخه 18 بحث کنند و ری اکت از این موارد فید بک بگیره !

و حالا چطور میتونیم ری اکت نسخه جدید آلفا رو نصب کنیم ؟

// for react-alpha
npm install react@alpha
// for react-dom alpha
npm install react-dom@alpha

با کامند های بالا میتونین ری اکت پروژه اتون رو به نسخه آزمایشی 18 ارتقا بدین ! راستی ری اکت معتقده آپدیت ری اکت اندازه یه بعد از ظهر یک روز ازتون وقت میگیریه و خیلی تغییرات اساسی تو کد بیستون نیاز نیست بدید بر خلاف تغییرات ری اکت 16 !

و حالا تغییرات اساسی ری اکت در نسخه پیش رو چیست ؟

اولین و مهمترین تغییر ری اکت در کدبیس اش اتفاق افتاده ! و درست در جایی که کامپوننت ها شروع به ری رندر شدن میکنند ! حتما دلایل ری رندر شدن یه کامپوننت رو میدونین که یکیش setstate شدن استیت هست

تغییری مهمی که ایجاد شده اینه که دیگر کامپوننت ها از بالا به پایین رندر نمیشن ! toptobottom rendering و در عوض قابلیت جدیدی اضافه شده که بهش میگن concurrency rendering یا رندر همزمان !

این قابلیت چیه و چیکار میکنه ؟

تا ری اکت 17 اتفاقی که می افتاد رو در پاراگراف قبلی توضیح دادم تمام کامپوننت ها بعد از ری رندر از بالا به پایین رندر میشدن ! ولی خب همین باعث یه سری ساید افکت های خیلی فجیعی میشد که به قول ری اکت کلی اییشو براش داشتن ، هر روز که روی بعضی کد ها و بعضی ساختار ها باعث ایجاد مشکل میشده مثلا فرض کنین یک سایت با کلی کامپوننت و همزمان بخاطر یه اینپوت همه از بالا به پایین رندر میشدن این عملیات مکرر باعث ایجاد لگ در کامپوننت های دیگ میشد ! که ری اکت مجاب کرد Memo رو در اون زمان اضافه کنه ولی واقعیتی که بود ری اکت رو مجاب کرد که برای حل این مسئله یه راه حل بهتری رو بده ، برای همین یه تیم روی این قابلیت experimental کار کردند و حتی براش داخل خود داکیومنت ری اکت هم داکیومنت کامل نوشتن تا کم کم اونو تو نسخه 18 اضافه اش کنند !

این تغییر اساسی در کد بیس ری اکت باعث شد تا اونا دستشون برای اضافه کردن قابلیت های بیشتر و جذاب تر باز بشه !

چگونه این قابلیت را فعال کنیم ؟

برای فعال کردن این قابلیت در ری اکت نیاز نیست تغییرات زیادی در کدمون ایجاد کنیم ! صرفا باید در index.js یه سری تغییرات در کدمون بدیم ! به طور مثال ما قبلا این شکلی کامپوننت app رو به div با آیدی روت اپند میکردیم !

import React from 'react';
import ReactDOM from 'react-dom';
const container = document.getElementById('root') 
ReactDOM.render(<App />, container);

و حالا تغییرات ما در ری اکت 18 اینچنین خواهد بود !

import React from 'react';
import ReactDOM from 'react-dom';
import App from 'App';
const container = document.getEleementById('root')
const root = ReactDOM.createRoot(container)
root.render(<App />)

با استفاده از این تغییر ما قابلیت concurrency Rendering رو فعال میکنیم ! و میتونیم از قابلیت های جذابش استفاده کنیم !

اما این تمام کار نیست ! ما با تغییرات این بخش میتوانیم تغییرات دیگ ای رو هم اعمال کنیم :

فعال کردن قابلیت hydrate :

import ReactDOM from ‘react-dom’;
import App from 'App';
const container = document.getElementById('root');
const root = ReactDOM.createRoot(container, { hydrate: true });
root.render(<App />);

با اضافه کردن این متغیر میتوانیم این قابلیت جدید را به ری اکت اضافه کنیم ولی این قابلیت دقیقا برای ما چه کاری رو انجام میده ؟

بزارید یک مثال از عملکرد Next js بزنیم !


همانگونه که در تصویر میبینید برای ساخته شدن یک صفحه توسط نکست جی اس 4 مرحله طی میشود

مرحله اول : تمامی صفحات ssr در ری اکت در زمان بیلد next js یکبار pre generate (یک غذای نیمه اماده رو تصور کنید ) میشوند ! زمانی که یوزر ریکوست برای صفحه ای میدهد آن صفحه سمت سرور کاملا ساخته میشود و با محتوای مورد نظر ما پر میشود !

مرحله دو : صفحه سمت مرورگر فرستاده میشود و نمایش میدهد ، همزمان js های مورد نیاز نیست دانلود میشود

مرحله سه : react به کانتنت ما تزریق یا hydrate میشود ! ( به این علت که ری اکت برای سرور به علت سر و کار داشتن با Dom که مستقیما مربوط به مرورگر است بیگانه است !) برای همین ما بعد از ساختن صفحات برای اینکه بتوانیم از قابلیت های ری اکت استفاده کنیم باید آن را به محتوایمان تزریق کنیم ( البته این حرکات رو نکست برامون میزنه)

مرحله 4: نمایش کانتنت و محتوای ما به همراه react !

حالا ری اکت با hydrate چیکار میکنه ؟

سال 2017 ، issue در گیت هاب ری اکت ثبت شد با این مضمون :

با مثالی که زده کاملا متوجه مشکل میشید ! فرض کنید ما یه همچین JSX ای داریم :

<div id=&quotcontainer&quot>
    <div class=&quotspinner&quot>Loading...</div>
</div>

و بعد میخواهیم این کار رو انجام بدیم :

ReactDOM.render(
   <div class=&quotmyapp&quot>
      <span>App</span>
   </div>,
  document.getElementById('container')
)

خروجی ای که میگیریم این هست

<div id=&quotcontainer&quot>
  <div class=&quotspinner&quot>
      <span>App</span>
  </div>
</div>

شاید فک کنین چه باگ بدی ولی واقعا این باگ نیست ، ری اکت داره کارشو درست انجام میده ، فقط برای SSR شدنش خیلی باید حرفه ای عمل کنید ! برای همین بود که خیلیا از نکست استفاده میکردند !

اتفاقی که اینجا میوفته یه دلیل خیلی ساده داره و اونم اینه که ری اکت میاد دو طرف مقایسه میکنه و چون ری اکت attribute هارو ضمیمه نمیکنه ( فارسی patch) برای همین اصلا براش مهم نیست اون کلاسش یه چیز دیگس این یه چیز دیگ با خود المنت کار داره ! میگه خب اونجا یه div میبینم اینورم div میبینم فقط تفاوتشون یه span عه پس اضافه اش میکنم به dom !

همین اتفاق خیلی ساده میتونه خراب کاری زیادی رو سمت server ایجاد کنه چون وقتی کانتنت شما آمادست ! ری اکت رو اگر با reactdom.render اگر رندر کنین این به جای تزریق درست و جایگزینی مناسب این اتفاق عجیب براتون رقم میزنه و بعدش میگید ری اکت چقد بده ! ولی خب در عوض در این نسخه با اضافه کردن اون متغیر تمامی این اتفاقات درست میشه و اگرم همچین اتفاقی بیوفته طبق ادعای یکی از اعضای core تیم ری اکت پیام وارنینگ در کنسول براتون نمایش داده میشه !

2. ارتقا render callback

تغییرات زیادی در این بخش شاهد نیستیم ولی دونستنش خالی از لطف نیست ! ری اکت قبلا بهمون اجازه میداد بتونیم بعد از رندر شدن همه کامپوننت ها ، کال بکی رو کال کنیم ! به طور مثال :

import React from 'react';
import ReactDOM from 'react-dom';
import App from 'App'
const container = document.getElementById('root')
ReactDOM.render(<App />, container, function(){
    console.log('render only after initial component rendering')
})
console.log('render at very last')

حالا تغییری که در این قسمت شاهدش هستیم این هست که میتوانیم برای کال بک در نسخه 18 از

requestIdleCallback

setTimeOut

استفاده کنیم !

3. UseTransition

در نسخه جدید ری اکت دو هوک جدید تا الان قرار است که به ری اکت اضافه بشه اولین هوک usetransition است ، از قابلیت های این هوک با استناد به داکیومنت ری اکت این مورد اعلام شده است که

which allows you “to tell React which updates are urgent, and which are not”.

بله این هوک باشعور میتونه تشخیص بده که کدوم آپدیت از اون یکی اهمیتش بالاتره و اول بره اونو انجام بده !!

اینجوری میشه برداشت کرد وقتی یه صفحه پر از کامپوننت داریم که مثلا یه سرچ اینپوت داریم که با تایپ کردن داخلش realtime دیتا فچ میشه و به یوزر نشون داده میشه و هر بار با تایپ کردن چون در پست زمینه ست استیت اتفاق می افته باعث ری رندر شدن همه این کامپوننت ها میشه و باعث ایجاد لگ در کل صفحه میشه و اعصاب یوزرا رو خرد میکنه !

طریقه استفاده از این هوک جذاب به این شکل هستش :

import {startTransition} from 'react';
//ضروری است: Update input value as type
setInputValue(input);
startTransition(()=>{
    //در وهله بعدی اجرا میشود: Show the search results
    setSearchQuery(input)
});


این قابلیت دقیقا باعث این میشه که کد ما آپدیت ترین استیت رو دریافت بکنه و از دریافت کرده استیت هایی که کاربر تایپشون کرده و بدرد نمیخورده خودداری بشه ! واقعا فوق العادست !

این هوک بیشتر برای دیتا فچ ، محاسبات سنگین و کارایی که نیاز به پردازش داره و زمان میبره میخوره ولی خب مواردی که ضرور هست رو باید خارج از این هوک بنویسیم مثل مثال بالا که اول ست استیت سرچ انجام شده و در پس زمینه داره فچ دیتا رو بر اساس اون استیت انجام میده !

اساس این آپدیت کلا بر موضوع smooth rendering هستش یعنی اینکه همه چیز باید کاملا در اتقان صنع و در آرامش اتفاق بیوفته نباید ری رندر های متوالی باعث ایجاد فلاش یا لگ بشه و یوزر بخواد اذیت کنه !

4.Strict Effects

قابلیتی در ری اکت و کلیت در زبان جاوا اسکریپت وجود داره به اسم strict mode ، کاری که این مود انجام میده رو با عنایت به داکیومنت ری اکت این شکلی میشه تعریف کرد


یک ابزاریه که اشتباهات کد زنی ما بهمون نشون بده و نزاره اپ کامپایل بشه تا زمانی که اون موارد درست شده و چون زبان جاوا اسکریپت به خودیه خود تا زمان کامپایل شدن هیچ خطایی به کاربر نشون نمیده این مود به ما کمک میکنه دیباگ کنیم کدمون رو و خب دقیقا داخل ری اکت هم فقط روی مود دولوپمنت اکتیو میشه و درست مثه تگ فرگمنت هیچ خروجی ui ای نداره !

حالا Strict Effects چیکار میکنه برامون ؟

این مود در strict mode میتونه فعال بشه و تمامی ساید افکت های اپلیکیشن ما رو بررسی کنه و خب عمده ساید افکت ها رو هم useeffect برای ری اکت ایجاد میکنه و باهاش میتونیم کلی کار باحال انجام بدیم ولی خب عملکرد این مود اینشکلیه که ساید افکت ها رو دو بار اجرا میکنه تا مطمین بشه ساید افکت خطرناکی برای اپتون پیش نمیاد ! درست مثه همون error معروف ، که وقتی بیش از اندازه set state صورت میگیره میبینمش اینم دقیقا وقتی ساید افکت در حسابی کد زده نشه بهمون خطا میده و خب میتونم بگم کمک خیلی خوبی میتونه بهمون بکنه ! قبل از این داستانا eslint پلاگینی برای ری اکت داده بود که به جرئت خوده منو خیلی جاها کمک میکرد مخصوصا موقع دپندنسی گذاشتن برای useeffect و پیشنهادم اینه فلن ازش استفاده کنید تا این ری اکت جدیده بیاد !! :)

5. بهبود حالت SSR

این مورد خیلی بیشتر توی hydrate توضیح دادیم ولی خب به طور خلاصه فهمیدیم نکست جی اس چیکار میکنه اول کانتنت ما رو میسازه بعد جاوا اسکریپت رو لود میکنه بعد ری اکت رو به کانتنت ما تزریق میکنه ولی خب با همه خوبیاش یه ایراد بزرگ داره و اونم اینه تا زمانی که کانتنت لود شده سمت ما و هنوز جاوا اسکریپت و ری اکت بهش تزریق نشده ، صفحه ما با اولین سایت جهان وب تفاوتی نداره ! (شوخی) یعنی هیچ قابلیتی نداره هیچ کاریم باهاش نمیتونیم بکنیم و این مورد زمانی خودشو نشون میده که اینترنت ما خیلی ضعیفه و واقعا اعصاب کاربرا رو میتونه خرد بکنه ! اما خب ری اکت همینجوری ننشسته و براش برنامه ویژه داره !!

2 پلن برای ارتقا SSR در ری اکت 18 برنامه ریزی شده !

Streaming HTML (یا استریم کردن صفحه html)

تصوری که از استریم کردن داریم یعنی به جای اینکه کل محتوا یهو بیاد سمتمون به شکل چانک چانک و کوچک کوچک بیاد تا زمان لود کامل سایت اولا یوزر یه چیزی داخل سایت ببینه و هم از نظر سئو بتونیم Time To Intract مون رو بیاریم پایین و بهبود سئو پیدا کنیم ! این اتفاقم دقیقا همینو برامون رقم میزنه ، قبلنا برای اینکه در CSR بتونیم یک کامپوننت رو وابسته به لودش توسط یوزر کنیم یعنی اینکه تا زمانی که یوزر سمتش نرفته یا کلیک نکرده لود نشه از LAZY استفاده میکردیم که بهش میگفتیم Code spiliting و همین امر در نکست جی با پکیج loadable اتفاق افتاده با این تفاوت که code spiliting نکست به شکل خودکار اتفاق میوفته و نیازی نیست ما دستی این عملیات انجام بدیم ولی خب ری اکت برای این مورد هم برنامه داره ! شما در lazy به کامپوننت suspense دسترسی دارید که میتونید تا زمان لود کامل کامپوننت به یوزر لودینگی نشون بدیم ولی خب همه این داستانا تا همین الان فقط سمت کاربر قابل پیاده سازی بود ! ولی الان یه خبر خوب دارم و اونم اینه تمام این اتفاقات سمت سرور نیز اتفاق میوفته یعنی شما فقط اون کامپوننتی که نیاز دارید براتون نمایش داده میشه .

برای استفاده ازش اینشکلی کد میزنیم :

<Page>
    <Article />
    <Suspense fallback={<Loader />}>
         <Comments />   
   </Suspense>
</Page>

در اینجا کامپوننت article لود میشه ولی منتظر کامنت نمیمونه تا زمانی که خود کامنت توسط استریم شدن html ساخته بشه و اضافه بشه ، تو این فاصله یوزر میتونه به کامپوننت مقاله دسترسی داشته باشه !!!


2.Selective hydration

پلن دوم ری اکت برای بهبود SSR ، اینه که هیچ کامپوننتی لنگ اون یکی کامپوننت نمیمونه تا صفحه جنریت بشه ! هر کامپوننتی که آماده بشه و کانتنت بهش برسه شروع میشه به هیدریت شدن توسط ری اکت و هیدریت شدن فقط یکبار اتفاق نمیوفته ! حتی انقدر این قسمت رو با وسواس پیش بردن که اگر یوزر اول به جای خاصی کلیک کنه یا اسکرولش رو قسمت خاصی باشه اول اون قسمت هیدریت میشه و ساخته میشه و بعد بقیه قسمتا !!! این مورد خیلی عجیب و خیلی فوق العادست !

5. Suspense List

قابلیت بعدی ری اکت لیست هایی هستند که شما میتونین به وسیله اون ها تعیین کنین که رندر شدن کامپوننت به چه شکل اتفاق بیوفته ! خب این یعنی چی؟ یعنی اینکه قبلا هیچ کنترلی رو کامپوننت هامون نداشتیم و هر کدوم زودتر از اون یکی تو هیج نظم و ترتیبی به محض گرفتن دیتا فچ میشدن ولی حالا با این قابلیت میتونیم تعیین کنیم که به چه نحوی قراره لود بشن

به سه حالت دسته بندی میشن : همزمان با هم لود شن ، از اول لیست به اخر ، از اخر به اول لیست

<SuspenseList revealOrder=&quotforwards&quot>
  <Suspense fallback={<LoadingSpinner />}>
    <CardComponent id={1} />
  </Suspense>
  <Suspense fallback={<LoadingSpinner />}>
    <CardComponent id={2} />
 </Suspense>
 </SuspenseList>


reveal order سه تا پراپ میگیره

forwards

backwards

together

که همینجور که از معنیش مشخصه اگر به ترتیب از اول به اخر باشه میشه فوروارد اگر برعکسش باشه میشه بکوارد و اگر باهم دیگه رندر صورت بگیره میشه together !

6.useDeferredValue

و در نهایت آخرین ویژگی که دومین هوکی هست که به این نسخه قرار بوده اضافه بشه همین هوک هستش ولی خب اگر لغوی معنیش کنیم به تعلل یا مکث یا معوق میرسیم و دقیقا کارشم همینه میتونه هر چیزی که بهش پاس میدین رو با تعویقی که خودتون براش تعیین میکنین بهتون پاس بده اینجوری میتونین بازهم استیت های بدرد نخوری که یوزر موقع تایپ کردن یا سرچ کردن مینویسه رو الک کنین ، همین ویرگول تصور کنین وقتی متنی مینویسین براتون میزنه در حال ذخیره ... ، حالا ویرگول وقتی ری اکت آپدیت بشه میتونه اولین نفر برای استفاده از این قابلیت باشه ، مثلا تعیین کنه استیت یوزر با تعلل 10 ثانیه یا 15 ثانیه اپدیت بشه !! اینجوری نیاز نیست مکرر برای آپدیت متن من ریکوست بزنه به سرور بیچارش !!

استفاده از این قابلیت اینشکلیه

function App() {
  const [text, setText] = useState(&quot&quot);
  const deferredText = useDeferredValue(text, { timeoutMs: 2000 }); 
  return (
    <div className=&quotApp&quot>
    <input value={text} ={handleChange} />
      <CardLists text={deferredText} />
    </div>
  );
 }

اون timeout که میگیره اون مقادر تعلل مورد نظر ماست !


بله بلاخره بعد از این توضیحات مفصل رسیدیم به انتهای مقاله ! اگر این مقاله رو دست داشتین لایک کنین و نظراتتون رو کامنت کنین برام ، نظرات و لایک هاتون باعث افتخار بنده است و خستگی ام این مدلی در میره !

منابعی که برای نوشتن مقاله استفاده شد :

https://chan.dev/posts/concurrent-mode-is-dead/

https://dev.to/cassidoo/react-18-alpha-is-out-now-what-2apj

https://github.com/reactwg/react-18/discussions/4

https://github.com/reactwg/react-18/discussions/37

https://dev.to/workshub/react-18-is-here-what-s-new-ah4

https://dev.to/muditdev/what-s-new-in-react-18-32m4


در نهایت اگر نیاز هست با من ارتباط بگیرید میتونین از لینکدین بهم پیام بدین :

https://www.linkedin.com/in/pouriya-babaali-2381661b5/