توی این پست میخوام یه معرفی کلی از تمام هوک های react js داشته باشم و خب برای کسانی که تازه این مسیر رو شروع کردن میتونه راهنمای خوبی باشه و دید نسبتا مناسبی بهشون درباره ی هوک های react js بده.
خب قبلش اصلا ببینیم هوک چیه ؟؟
در نسخه های قبل react برای مدیریت state ها و لایف سایکل برنامه و چیز های دیگه از کلاس کامپوننت ها استفاده میکردیم و فقط زمانی که یه کامپوننت stateless یا بدون state بود از فانکشنال کامپوننت ها استفاده میکردیم ، اما در نسخه ی 16.8 هوک ها معرفی شدن که این خبر بسیار خوبی بود برای برنامه نویس ها ، چون هم کار راحت تر میشد و هم اکثر وقت ها کد کم تری نوشته میشد و خب چی از این بهتر ؟! در نتیجه دیگه فقط برای نوشتن کامپوننت های stateless از فانکشنال کامپوننت استفاده نمیشد بلکه میشد کل یک پروژه رو به شکل فانکشنال نوشت که خب الان هم اکثر پروژه ها دیگه فانکشنال هستن و کمتر کسی هست که از کلاس کامپوننت استفاده کنه مگر به دلایل دیگه ای که خود اون شخص میدونه و مایل هست که فانکشنال ننویسه یا چند تا از کامپوننت هاش رو فانکشنال نکنه و کلاس کامپوننت استفاده کنه .
*** اگه state براتون آشنا نیست یا میخواین یکم بیشتر باهاش آشنا بشین ، میتونین قبل از شروع ، این مطلب هم بخونین :
خب بریم سراغ معرفی هوک های ری اکت ...
هوک های اصلی و پر کاربرد react این سه تا هوک هستن :
useState :
اولین هوک و البته پرکاربرد ترین هوک react چیزی نیست جز useState که از این هوک برای مدیریت state های برنامه استفاده میکنیم و این همون هوکی هست که به ما اجازه میده وقتی فانکشنال کامپوننت مینویسیم بتونیم توش state تعریف کنیم و مقادیر state های خودمون رو تغییر بدیم و نحوه ی استفاده از این هوک هم به این شکل هست :
const [state, setState] = useState(initialState);
که در قسمت state ما نام state خودمون رو انتخاب میکنیم ، برای مثال میخوایم لیست دانش آموزان رو بریزیم توی یک state پس میایم و نام state رو میذاریم students ، قسمت دوم که میشه setState متدی هست که قراره state ما رو مدیریت کنه و مقدارش رو عوض کنه و معمولا هم نام گذاریش به این شکل هست که قبل از نام state یه دونه set قرار میدیم ، توی مثال ما میشه setStudents ، در سمت راست مساوی هم اسم هوک نوشته شده و همچنین توی پرانتز ها مقدار اولیه ای که state ما میخواد داشته باشه رو مینویسیم ، در مثال ما مقدار اولیه میشه یک آرایه ی خالی که به این شکل توی پرانتز مینویسیمش : [ ]
useEffect :
هوک بعدی ای که میخوام بهتون معرفی کنم هم یک هوک پرکاربرد هست که برای این که با استفاده از لایف سایکلِ react عملیات مختلفی انجام بدیم و ساید افکت ها رو مدیریت کنیم ازش استفاده میکنیم ، به این دلیل که خب دیگه توی فانکشنال کامپوننت ها ما نمیتونم از چیز هایی که برای کلاس کامپوننت استفاده میکردیم استفاده کنیم مثل componentDidMount ، و به جاش از این هوک استفاده میشه ، نحوه ی استفادش هم به این شکل هست :
useEffect( ( ) => { } , [ ] )
که یک کال بک فانکشن میگیره و زمانی که صفحه ی ما render میشه اجرا میشه و در حالت دیفالت یعنی وقتی که بعد از کال بک فانکشن خودمون [ ] رو نذاریم با هر بار re-render شدن کامپوننت این فانکشن هم اجرا میشه اما در صورتی که بخوایم فقط یک بار اجرا بشه بعد از فانکش یک ارایه ی خالی رو قرار میدیم و این باعث میشه که فانکشن ما فقط موقع اولین رندر صفحه اجرا بشه ، و در صورتی که بخوایم بعد از تغییر یک مقدار خاص فانکشن ما صدا زده بشه اون مقدار رو داخل [ ] قرار میدیم ، در کل این [ ] رو ارایه ای از وابستگی ها بهش میگیم که اون وابستگی هایی که طبق تغییر اون ها بخوایم useEffect اجرا بشه رو داخلش قرار میدیم .
useContext :
از این هوک برای جلوگیری از Prop drilling استفاده میشه ، Prop drillin حالتیه که وقتی ما prop رو بین چند لایه از کامپوننت هامون هی پاس میدیم رو به پایین تا به کامپوننتی که میخوایم برسه ، که خب این باعث میشه که کد ما خوندنش سخت بشه و خودمونم کارمون بیشتر بشه ، برای مثال اگر شما یک prop دارین که در لایه ی بالایی هست و قراره سه لایه پایین بره و به کامپوننت مد نظرتون برسه ، خب باید هی این prop رو یکی یکی پاس بدین پایین تا برسه جایی که میخواین و این کار جالبی نیست ، این هوک این مشکل رو حل میکنه و prop ها رو یک جا نگه میداره و هر جایی که ما نیاز داشتیم از اون prop استفاده میکنیم بدون این که نیاز باشه از جایی به کامپوننت خودمون پاسش بدیم .
const value = useContext(MyContext);
در اینجا ما value رو از کانتکسی که ساختیم به نام MyContext داریم میگیریم و ازش توی کامپوننتمون استفاده میکنیم و از جایی بهمون پاس داده نشده .
خب ... این سه تا هوک اصلی و پرکاربرد react بودن ... اما چند تا هوک دیگه هم هست که شاید اندازه ی این سه تا هوک پر کاربرد نباشن ولی قطعا کاربرد خودشون رو دارن و از هر کدوم میشه جایی استفاده کرد و میتونن مشکل مارو حل کنن یا کد مارو بهتر کنن .
useReducer :
قبل از معرفی این هوک بهتره که reducer رو یه معرفی کوتاه بکنم ، reducer رو اگه بخوام ساده بگم چیزیه که یک state قدیمی رو میگیره و روی اون عملیاتی انجام میده و در نهایت به ما یک state جدید میده ، میتونین reducer رو یک قهوه ساز در نظر بگیرین که بهش قهوه رو میدیم که اینجا همون state ما هست و سپس reducer میاد یک سری عملیات (action) روی قهوه انجام میده و یک state جدید بهمون برمیگردونه که میشه قهوه ی تازمون ... خب حالا این هوک میاد چکار میکنه ؟ زمانی که ما برنامه ای داریم که state های اون به هم مرتبط هستند بهتره که از useReducer استفاده بکنیم ، اگر بخوایم یک counter رو باهاش پیاده سازی کنیم به این شکل میشه (این مثالِ خود داکیومنتِ react هست ) :
مشاهده میکنید که این هوک یک state رو داره و از dispatch استفاده میکنه که dispatch یک فانکشن هست برای صدا زدن آبجکت های اکشن های ما . و در سمت راست علامت مساوی یک reducer وجود داره که توضیح دادم کارش چیه و مقدار اولیه ، و در نهایت وقتی دکمه کلیک میشه عملیات انجام میشه و مقداری که توی state ذخیره کردیم که در اینجا count هست تغییر میکنه .
useCallback :
بهتره قبلش بدونیم که callBack چیه ؟ callBack تابعی هست که توسط یه تابع دیگه صدا زده میشه ، این صدا زدن زمانی اتفاق میوفته که عملیاتی که به تابع اول داده شده به اتمام برسه بعدش callBack ما صدا زده میشه . و خب همونطور که احتمالا متوجه شدین ، useCallBack هم یک هوک هست که یک تابع رو میگیره و اون رو کَش میکنه یا به نوعی تو مموری ذخیرش میکنه و به ما تحویل میده ، و این خروجی ای که یک تابع هست تنها زمانی تغییر میکنه و از اول کش میشه که تابع ورودی ما یکی از مقادیرش تغییر کنه ، در اون صورت این هوک یک تابع جدید برمیگردونه و در غیر این صورت همون تابعی که توی این هوک کش شده برگشت داده میشه .
در react به این عمل که تابع ما کش میشه یا ذخیره میشه توی این هوک Memoization یا به خاطر سپردن گفته میشه و به نوعی این هوک به ما یک کال بک memoized برمیگردونه .
و به این شکل هم نوشته میشه :
useCallback( someFunction() }, [dependencies])
در نهایت این که استفاده از useCallBack از render های اضافی برنامه جلوگیری میکنه و performance برنامه رو بهتر میکنه .
useMemo :
عملکرد این هوک هم شبیه به useCallBack هست با این تفاوت که به جای یک تابع در اینجا ما به جای این که یک فانکشن رو برگردونیم یک مقدار memoized شده رو برمیگردونیم .
و به این شکل هم نوشته میشه :
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useRef :
با استفاده از این هوک ما میتونیم به شکل مستقیم به المنت های DOM دسترسی پیدا بکنیم برای مثال ما میتونیم به برناممون با استفاده از این هوک بگیم که وقتی صفحه render شد روی یک اینپوت فوکِس بکنه یا کار هایی شبیه به این ، و به این شکل هم نوشته میشه :
const refContainer = useRef(initialValue);
که در سمت چپ یک متغیر هست که آبجکتی که این هوک برمیگردونه رو در اون داریم ذخیره میکنیم و در سمت راست تساوی خود هوک هست که مقدار اولیه رو در پرانتز بهش میدیم ، ما میتونیم با استفاده از مقدار current که در آبجکتی که برگشت داده میشه هست ، از ویژگی های المنت هامون استفاده کنیم ، مثلا میتونیم بنویسیم ()refContainer.current.focus و با این دستور روی اون اینپوتی که ref رو بهش نسبت دادیم فوکِس میکنیم .
اینم از هوک هایی که بیشتر ازشون استفاده میشه ، و اما خود سایت react چند تا هوک دیگه هم علاوه بر این ها معرفی کرده که در اینجا به طور خلاصه اون هارو هم معرفی میکنم :
useImperativeHandle :
زمانی که ما یک ref یا همون ارجاع رو به کامپوننت پدر ارسال کنیم برای ویرایش کردن اون ref میتونیم از این هوک استفاده کنیم ، و این هوک هم به این شکل هست :
useImperativeHandle(ref, createHandle, [deps])
که در اینجا ref همون ارجاعی هست که به کامپوننت پدر ارسال کردیم و createHandle اون تابعی هست که روی ref قراره اجرا بشه و deps هم آرایه ای از وابستگی ها هست که توی بخش useEffect توضیح دادم .
useLayoutEffect :
این هوک شبیه به useEffect هست با این تفاوت که useEffect بعد از این که صفحه render شد و به کاربر نمایش داده شد اجرا میشه ولی useLayoutEffect قبل از این که صفحه render بشه و به کاربر نمایش داده بشه اجرا میشه .
useDebugValue :
و آخرین و شاید کم کاربرد ترین هوک هم useDebugValue هست که برای زمانی استفاده میشه که میخوایم مقدار یا فانکشنی رو دیباگ کنیم ولی نمیخوایم خیلی عملکرد برناممون پایین بیاد و یا تاثیری توش انجام بشه ، اون موقع از این هوک استفاده میکنیم و این هوک فقط زمانی اجرا میشه که React DevTools باز باشه .
نکته ای که هست اینه که اگر خواستین تعریف بهتر و کامل تری درباره ی این سه تا هوک بخونین بهتره که به این لینک مراجعه کنید : لینک
از اونجایی که نسخه ی 18 ری اکت سال 2022 معرفی شد چند تا هوک جدید هم به ری اکت اضافه شد که لازم دونستم اون هارو هم به این هوک ها اضافه کنم تا هر وقت کسی میخواد این مطلب رو بخونه با این هوک ها هم آشنا بشه ...
useDeferredValue :
این هوک یک مقدار رو میگیره و یه کپی از اون برمیگردونه و نمایش میده تا زمانی که ما نیاز داریم که به صورت فوری مقدار اپدیت بشه کندی کم تری رو تجربه کنیم برای مثال وقتی که ما یک لیست طولانی داریم از داده ها و یک اینپوت داریم که میخوایم زمانی که کاربر متن رو وارد کرد همزمان اون مقادیری که داریم تغییر کنن ، خب در حالت های عادی ما از صفحه بندی استفاده میکنیم که نیاز نباشه تمام دیتا رو با هم نمایش بدیم یا از راه های دیگه ... اما خب اگه لازم باشه که اطلاعات رو با هم نمایش بدیم به این هوک نیاز پیدا میکنیم ، از این هوک وقتی باید استفاده کرد که دیتایی که میگیریم از یه لایه ی بالاتر بیاد و ما کنترلی روی ست کردن اون مقدار نداشته باشیم توی کامپوننت خودمون ، در اون صورت ما دیتامون رو به این هوک میدیم به این شکل :
const deferredValue = useDeferredValue(value);
و حالا مقدار ما با کندی کمتری تغییر میکنه و تجربه ی کاربری بهتری رو ارائه میدیم .
useTransition :
این هوک هم یه جورایی برای موقعیت هایی شبیه موقعیتی که از هوک useDeferredValue استفاده میکنیم استفاده میشه و کاربردی مثل اون داره یه جورایی ، اما وقتی باید ازش استفاده کنیم که ما کنترل روی ست کردن مقادیرمون داریم .
این هوک به این شکل استفاده میشه :
const [isPending, startTransition] = useTransition();
همونطور که میبینید ما یک هوک داریم که با خودش دو تا المنت isPending و startTransition رو داره ، ما از تابع startTransition برای این استفاده میکنیم که تابع های ست کردن اون استیت هایی که اهمیت کم تری دارند رو داخلش قرار میدیم و بهش میگیم که این استیت که قراره ست بشه رو دیرتر ست کن و خب این باعث میشه همزمانی ست کردن استیت ها از بین بره و یا کم بشه که در نهایت تجربه ی کاربری بهتری ارائه میدیم و سرعت اجرای برنامه بالاتر میاد ، و isPending هم یک مقدار بولین هست که میتونه true یا false باشه که وقتی ازش استفاده میکنیم که میخوایم موقعی که startTransition داره اون ست کردن رو دیر تر انجام میده به کاربر یه پیام یا لودینگ برای مثال نمایش بدیم .
useId :
بالاخره ری اکت دست به کار شد و هوک خودش رو برای ایدی های یونیک معرفی کرد تا دیگه نیاز نباشه برای ساختن ایدی های رندوم و یونیک از پکیج دیگه ای استفاده کنیم ، که خب این خیلی خوبه و برای اینجور مواقع خیلی کاربردیه ، روش استفاده ازش هم به این شکل هست :
const id = useId() ;
در کنار این سه هوک ، ری اکت چند تا هوک دیگه هم برای کتابخونه هایی که برای ری اکت ساخته شده هست و اون ها میتونن از این هوک ها استفاده کنن و معمولا توسعه دهندگان ری اکت خیلی با این هوک ها سر و کله نخواهند زد ، من هم توضیح خاصی نمیدم ولی اینجا معرفیشون میکنم که باهاشون آشنا بشین :
useSyncExternalStore :
از این هوک برای وقتی استفاده میشه که قراره از یه منبع خارجی یک سری دیتا بخونیم یا حالا از اون ها استفاده کنیم که برای بهتر شدن عملکرد در همزمانی استفاده میشه ، که به این شکل هم هست :
const state = useSyncExternalStore(subscribe, getSnapshot[, getServerSnapshot]);
useInsertionEffect :
این هوک عملکردی مثل useEffect داره با این تفاوت که قبل از این که DOM اجرا شده باشه عمل میکنه .
و ازش برای تزریق کردن یا اضافه کردن استایل به DOM استفاده میشه قبل از این که layout توسط هوک useLayoutEffect خونده بشه کارش رو انجام میده .
به این شکل هم هست :
useInsertionEffect(didUpdate);
خب اینم از تمام هوک های react js ... امیدوارم که تونسته باشم بهتون یه دید کلی درباره ی این هوک ها داده باشم و کمکتون کرده باشم که کارتون رو راحت تر شروع کنید :)
موفق و خوشحال باشین ;)