ری اکت ۱۹ با یه سری تغییرات جدید و جذابی منتشر شده که توی این پست قراره بهشون بپردازیم.
این تغییرات شامل فیچر های جدید٬ بهبود٬ حذف و یا جایگزینی فیچر های فعلی هستش.
تغییراتی که باعث میشه ما به عنوان دولوپر با کد کمتر٬ خروجی بیشتر و بهتری بگیریم.
تمام تغییراتی که در این پست دربارش صحبت میکنیم:
1. React Compiler
2. forwardRef => Ref as a prop
3. Document Metadata
4.Server Components
5. Actions
6. New Hooks (use(), useFormStatus(), useOptimistic(),
یکی از مشکلایی که توی ری اکت از زمان های خیلی دور وجود داشت ری رندر های اضافه اس که به پرفورمنس پروژه آسیب میزنه. این اصن منطقی نبود که وقتی پراپی که میگیریم تغییری نکرده٬ بیایم کامپوننت رو ری رندر بکنیم صرفا برای اینکه کامپوننت پدر ری رندر شده. حالا فک کنید کلی کامپوننت تو در تو داشتیم که اینا هیچ کدوم نیاز به ری رندر نداشتند چون اصلا پراپشون تغییری نکرده اما فقط چون کامپوننت پدر ری رندر شده همه ی این کامپوننت ها هم ری رندر میشدن و سرعت وبسایت رو میاوردن پایین.
برای حل این مشکل تیم ری اکت تکنیک هایی رو معرفی کرد تا بتونیم با استفاده ازشون دیتایی که به عنوان پراپ پاس داده میشن رو به اصطلاح به یادسپاری یا memoize کنیم تا از ری رندر اضافه جلوگیری کنیم.
این تکنیک ها استفاده از useMemo, useCallback, Memo بود.
اما مشکلی که این روش داره اینه که اولا واقعا خیلیا نمیدونن دقیقا چه موقعی مناسبه این تکنیک هارو استفاده کنند و ممکنه اون ری رندر ارزشش رو نداشته باشه و بدتر به پرفورمنس آسیب بزنه از اونجایی که خود این هوک ها یه پروسه ی مقایسه ی پراپ قبلی و پراپ جدید دارند. ( اطلاعات بیشتر رو میتونید توی این مقاله که درباره بهبود پرفورمنس پروژه های ری اکتی نوشتم بخونید)
دوما که تجربه دولوپر یا Developer Experience جالبی هم ندارن بنظرم.
حالا بعد از کلی فیدبک از کامیونیتی و صرف زمان زیاد٬ تیم ری اکت بلخره اعلام کردند که روی کامپایلر ری اکت کار کردند و دارند روی اینستاگرام استفادش میکنند و بزودی توی ورژن های بعدی ریلیزش میکنند.
این کامپایلر میاد کد ری اکت شمارو به جاوااسکریپت خالص تبدیل میکنه و در پشت پرده خودش اون پروسه ی بهبود پرفورمنس و memoization رو انجام میده که دیگه شما نیازی به استفاده از اون هوک ها نباشید.
پس به این ترتیب useCallback , useMemo و memo به همین راحتی از ری اکت پر پر میشن و کار رو برای ما ساده تر میکنند.
ما قبلا وقتی یه متغیر داشتی که برابر با useRef بود و اگه میخواستیم این متغیر رو پاس بدیم به یه کامپوننت فرزند تا اونجا استفاده بشه از forwardRef استفاده میکردیم تا بتونیم علاوه بر پراپ ها اون رفی که پاس داده شده رو هم بگیریم استفاده کنیم. به این شکل:
اما حالا دیگه نیازی به این کار نیست و مستقیم میتونیم رف رو به عنوان پراپ پاس بدیم. به این شکل:
پس به این صورت به forwardRef هم دیگه نیازی نیست.
توی ورژن های قبلی ری اکت هر وقت میخواستیم تو jsx یه کامپوننت یه سری تگ به هد اضافه کنیم مجبور بودیم از لایبرری هایی مثل React Helmet استفاده کنیم ولی الان میتونیم مستقیم تو jsx تگای متا و لینک و.. که برای هد هستن رو بزاریم و خود ری اکت به صورت اتوماتیک میاد تشخیصشون میده و برشون میداره میزاره تو تگ head:
مبحث server component و client component مدت زیادیه که هست و توی Next.js ازش زیاد استفاده میکنیم.
به طور کل کامپوننت های سرور ساید کامپوننت هایی هستند که سمت سرور موقع بیلد ساخته میشن و با قرار نگرفتن در باندل جاوااسکریپت باعث کاهش سایز اون و بهبود پرفورمنس میشند و یه سری مزایای دیگه هم دارند:
۱. بهبود SEO: کامپونننت های سرور ساید چون سمت سرور ساخته رندر میشند و به صورت html اماده ریترن میشن٬ crawler های سرچ انجین به محتوای بیشتری دسترسی دارند و همین باعث بهبود seo میشه . تو کدای سمت client چون کامپوننت ها سمت کلاینت ساخته میشند و توسط جاوااسکریپت به طور داینایک محتوای صفحه رو اپدیت میکنند اولش هیچ محتوایی وجود نداره و page source خالیه و crawler ها هیچی پیدا نمیکنند.
۲. بهبود پرفورمنس: همونطور که تو مورد اول اشاره شد چون کامپوننت های سرور ساید موقع بیلد سمت سرور ساخته یا pre-built میشند سرعت لودشون بسیار بالاست و نتیجتا پرفورمنس بهتری دارند.
۳. امنیت : سرور کامپوننت ها اجازه میدند که دیتای حساسمون مثل توکن ها و api key ها سمت سرور بمونند و در سمت کلاینت قابل دسترس نباشند که امنیت سایت رو بالاتر میبره.
حالا اینا مزایای درشتش بود و اگه فقط همینارو در نظر بگیریم ری اکت با دیفالت کلاینت ساید بودنش در ورژن های قبلی مزیت های بزرگی رو از دست میداد که توی ورژن اخیر server component رو اضافه کرد. هرچند برخلاف نکست٬ ری اکت کامپوننت ها بای دیفالت هنوز کلاینت ساید هستند و اگه بخوایم سرور ساید رندر بشند باید به خط اول کامپوننتمون دایرکتیوی به این شکل اضافه کنیم
'use server'; import React from 'react'; ...
اکشن ها قابلیت جدیدی هستن که به ری اکت اضافه شدند و نحوه ی کارکردن با فرم ها توی ری اکت رو تغییر میدن. ما قبلا از روی دکمه ی سابمیت در فرم استفاده میکردیم و همچنین استیت هایی برای دسترسی به مقادیر اینپوت های داخل فرم نیاز داشتیم تا دیتای فرم رو سابمیت کنیم الان با استفاده از اتربیوت action روی تگ form میتونیم دیتاشو بگیریم و سابمیت کنیم به این شکل:
همونطور که میبینید action برابر یه فانکشن هستش که دیتای توی اون فرم رو توی پارامتر اول بهمون برمیگردونه و میتونیم با متد get ای که داره اسم هر اینپوت داخل فرم رو بهش بدیم و مقدار سابمیت شده رو بگیریم.
تو سکشن بعد هوک های جدیدی که اضافه شده رو معرفی کنم شاهد بهبود های حتی بیشتری هم در هندل کردن فرم ها خواهیم بود.
این دو هوک های جدیدی هستند که به ری اکت اضافه شدند تا کار با فرم هارو برامون راحت تر کنند.
این هوک بهمون اجازه میده که یه استیتی داشته باشیم و مقدار اون استیت رو بر مبنای ریزالتی که توی اون هندلر اکشن فرم ریترن میکنیم٬ ست کنیم. بیاید یه مثال ببینیم:
کد بالا حالتیه که توش از اکشن و هوک useFormState استفاده نشده و میبینیم که سه تا اینپوت تعریف شده برای اینپوت ها و مسیج که از ریکوستمون برمیگرده.
حالا همین رو با استفاده از اکشن و هوک useFormState مینویسیم:
توی کد بالا استیت ها حذف شدن چون دیگه پارامتری که هندلر فرم اکشن برمیگردونه دیتای name و email رو توش داره و برای مسیج هم از هوک useFormStatus استفاده شده.
این هوک مثل استیت یه ارایه برمیگردونه که مقدار اولش مقداریه که از اکشنش ریترن میشه و مقدار دومش همون فانکشن اکشنش هست که میزاریمش توی اتریبیوت action فرممون. مقادیری که هوک میگیره هم اولیش فانشکنیه که میخوایم موقع اکشن فرممون صداش کنیم و چیزی ک برمیگردونه میره تو همون message قرار میگیره و مقدار دومی که میگیره initial Value ای هست که میخوایم message داشته باشه.
فک کنید میخوایم ارور و لودینگ هم به فرممون تو مثال بالا اضافه کنیم. بیاید اول با روال سابق کدش رو ببینیم:
حالا بیاید با استفاده از اکشن و هوک های جدیدمون ببینیم:
توی کد میبینیم که دکمه ی سابمیت رو بردیم توی یه کامپوننت جدا و اونجا از هوک useFormStatus استفاده کردیم که این هوک یه ابجکت برمیگردونه که شامل پراپرتی های data و panding و یه سری پراپرتی های دیگه که خیلی کاربردی ندارن هستش.
پراپرتی data همون دیتاییه که از فرم بدست اومده و سابمیت شده و پراپرتی پندینگ هم یه بولین هست که تا زمانی که فرم اکشنمون ریزالتی برنگردونه و پندینگ باشه این پراپرتی ترو هست و بعد با موفقیت یا شکست پرامیس اکشنمون٬ پراپرتی pending فالس میشه.
نکته: یکی از بدی های این هوک اینه که نمیتونی توی همون همون هوکی که فرم وجود داره استفادش کنی و این هوک فقط وضعیت فرم کامپوننت پدر رو بهتون میده:
این هوک که تازه به ری اکت اومده چند کاره اس و کارش آسون تر کردن روند گرفتن دیتا از سورس خارجی و همینطور کانتکست هستش:
جوری که قبلا دیتا رو میگرفتیم:
ما نیاز به یه استیت داشتیم و همینطور یه یوزافکت که دیتارو داخلش فچ کنیم و توی استیت ست کنیم.
حالا با هوک uas نیازی به استیت و یوزافکت نداریم :
حالا یه چیز باحال تر که میتونیم انجام بدیم که user experience بهتری داشته باشیم اضافه کردن یه لودینگ هست تا وقتی که دیتا فچ میشه. مطمعنا میدونید که توی روال قبلی باید یه استیت لودینگ هم اضافه میکردیم ولی اینجا با استفاده از suspense ری اکت کار رو برامون راحت تر کرده:
با پیچیدن کامپوننت Suspense دور کامپوننتمون و اضافه کردن یه لودینگ به عنوان fallback این کامپوننت تا زمانی که دیتارو نگرفته بهمون لودینگ رو نشون میده که این بهبود assets loading توی ورژن جدید ری اکت رو نشون میده و به نوعی میتونیم اینو پایان React.lazy هم بدونیم نه فقط بخاطر این کیس بلکه بخاطر اضافه شدن server componet ها و pre-render شدن سمت سرور و.. که تا حدی مارو بی نیاز از react.lazy میکنه.
۲. استفاده دوم از use برای گرفتن دیتا از کانتکست هستش.
قبلا از هوک useContext توی کامپوننت ها استفاده میکردیم تا دیتای موجود در کانتکستمون رو بخونیم :
الان از همون use هم میتونیم استفاده کنیم:
این خیلی فرق بزرگی ایجاد نکرده ولی در کل اگه دارید توی یه کامپوننت از use استفاده میکنید میتونید ازش برای خوندن کانتکست هم استفاده کنید و نیاز نباشه یه هوک دیگه هم ایمپورت کنید.
نکته: توی ورژن جدید ری اکت بجای </ Context.Provider> از </ Context> استفاده میشه و نیازی به گذاشتن اون کلمه ی provider نیست.
این هوک تو جاهایی که نیاز به اینتراکشن با سرور دارید مثل برنامه های real-time به درد میخوره. مثلا فک کنید وقتی یه پستی رو لایک میکنید دارید درواقع به سرور یه دیتایی میفرستید که اون لایک رو ثبت کنه یا مثلا وقتی پیامی میفرستید به کسی درواقع به سرور دارید دیتایی میفرستید که اون پیا رو ثبت کنه و توی چت باکس پیامش رو نشون بدیم. حالا فک کنید ممکنه چند ثانیه طولبکشه تا این لایکه یا پیاه به سرور برسه و موفق شه٬ این وسط یوزر قراره ببینه که با لایک یا فرستادن پیام هیچ اتفاقی نمیفته! نه پست لایک میشه نه پیام فرستاده میشه..
اینجاس که با این هوک یه اپدیت خوشبینانه انجام میدیم به این صورت که با کلیکش میایم فرض رو بر این میگیریم که دیتا رفت تو سرور ثبت شد پس خودمون قبل اومدن دیتای اپدیت شده از سرور٬ میایم یه دیتای فیک وارد میکنیم که انگار از سرور اومده و موفق بوده و کاربر درجا میبینه که لایک شد. حالا وقتی دیتای واقعی از سرور اومد دیتای فیک مارو جایگزین میکنه و کاربر متوجهش نمیشه و چون به محض لایک میبینه که پست لایک شده و با اومدن دیتای واقعی دیتا تغییری نمیکنه. یا مثلا پیام رو که میفرسته ما اون پیام رو ثبت شده در نظر میگیریم و درجا تو چت باکس نشونش میدیم تا کاربر فک کنه که که پیامش ثبت شده. به این روش میگن اپدیت optimistic یا خوشبینانه همونطور که از اسم هوکش پیداس.
توی مثال بالا میبینیم که یه استیت messages داریم که مسیجای واقعی رو توش داره و هوک useOptimistic رو داریم که دوتا پارامتر میگیره اولی همون مقدار initial اش هست که برابر با همون مسیجای واقعی هستشو یه کال بک میگیره که به صورت خوشبینانه بیاد مسیجای قبلی رو به اضافه مسیج فیک خودمون برگردونه. این هوک یه ارایه شامل دوتا مقدار برمیگردونه اولیش همون دیتاییه که از کال بک ریترن میشه و دومیش همون کال بکه هستش که بتونیم جایی که میخوایمش صداش کنیم و خوشبینانه دیتارو اپدیت کنیم.
توی jsx بجای مسیج های اصلی روی مسیج های optimistic یا همون optimisticMessages مپ میریم تا چون این علاوه بر مسیجای قبلی مسیج فیک ما هم شاملش میشه در حالی که استیت messages دست نخورده اس. حالا یه فرم داریم که اینپوت مسیج رو داره و وقتی کاربر مسیجش رو مینویسه و سابمیت میکنه داخل فانکشن sendMessage میبینیم که اول میاد اون فانکشن خوشبینانمون رو صدا میزنه و مسیج رو بهش پاس میده تا optimisicMessages رو اپدیت و در نتیجه سریع UI رو اپدیت کنه و بعد مسیج رو میفرسته سمت سرور که دیتای اصلی رو اپدیت کنه و وقتی دیتا برگشت حالا messages که حاوی دیتای اصلی هستش رو اپدیت میکنه و باعث میشه که optimisticMessages هم با دیتای واقعی رفرشبشه و اون فیکه با مسیج واقعی جایگزین بشه.
این بود تمام تغییرات بزرگی که در ری اکت ۱۹ شاهدش بودیم.
امیدوارم که بدردتون بخوره و لذت برده باشید.