تو پست قبلی درمورد متد های lifeCycle در کلاس کامپوننت ها صحبت کردیم و کارایی تک تکشون رو گفتیم که قبل از ورژن 16.8 ری اکت ما برای نوشتن کامپوننت های stateful و فیچر های دیگه ازشون در کلاس کامپوننت ها استفاده میکردیم؛ اما بعد از ورژن 16.8 ، هوک ها اومدن و همه چیزو تغییر دادن ، طوری که دیگه لازم نبود برای نوشتن کامپوننت های stateful از کلاس کامپوننت استفاده کنیم و فانکشنال کامپوننت با استفاده از هوک ها تقریبا همه ی چیزایی که با کلاس کامپوننت ممکن بود رو بهمون داد، ما امروز میخوایم درمورد یه سری از این هوک ها صحبت کنیم که خودِ ری اکت برامون به جا گذاشته و تقریبا همیشه از اکثر این هوک ها استفاده میشه.
ساید افکت چیست؟ !
وقتی یه فانکشن مینویسیم که اجزای داخلش به یه چیزی در بیرونِ اسکوپ خودش تاثیر میزاره میگن ساید افکت. برای مثال: data fetching ، دستکاری دام ، ست کردن و گرفتن لوکال استوریج ، setInterval و setTimeout و...
با استفاده از هوک useEffect ما هر ساید افکتی که داریم رو میتونیم داخل این هوک اجرا کنیم اگه توی پست قبلی یادتون باشه ما اینکارو با componentDidMount و componentDidUpdate انجام میدادیم، خب این هوک جفت متد رو باهم تو خودش داره و فرق با این دو متد لایف سایکل اینه که:
متد های لایف سایکل بعد از اجرا شدن رندر و قبل از پینت شدن محتوا اجرا میشن و اگه ui رو داخل این متد ها دستکاری کنیم ،متوجهِ تفاوتی که بین ui اپدیت شدمون و ui قبلی اتفاق افتاد نمیشیم چون قبل پینت شدن روی صفحه دستکاری رو اعمال کردیم
اما هوک useEffect دقیقا بعد از پینت شدن ui میاد اجرا میشه و اگه مثلا بک گراند یه المنت رو از داخل این هوک از سفید به قرمز تغییر بدیم، حتی واسه یه لحظه هم که شده اول بک گراند قبلی که سفیده رو میبینیم و بعد بک گراند به رنگ قرمز در میاد که اینجا یه امتیاز مثبت واسه متد لایف سایکل به حساب میاد که البته با هوک useLayoutEffect میتونیم میتونیم همون ویژگی لایف سایکل رو با این هوک به وجود بیاریم که جلوتر درموردش حرف خواهم زد.
پینت شدن چیست؟
بعد از اجرا شدن رندر ،مرورگر محتوایی که ریترن شده رو روی صفحه به نمایش در میاره که اصطلاحا بهش painting میگن.
به طور کلی میتونیم به useEffect به این شکل نگاه کنیم که یه هوکه که خودش سه تا متد componentDidMount و componentDidUpdateو componentWillUnmount رو اجرا میکنه ، اما به چه شکل
توی عکس بالا useEffect به سه شکل برای سه متد اجرا شده تا دقیقا همون کارایی متد لایف سایکل رو داشته باشه که اینجا به ترتیب توصیح میدمش
useEffect(() => { //side Effecst },[ ])
به طور کل useEffect دو تا آرگیومنت میگیره که اولی یه کال بک هستش که ساید افکت هامون رو توش مینویسیم و آرگیومنت دوم یه آرایه اختیاری هستش که میتونیم بزاریم یا نزاریم و با خالی گذاشتنش مثل کد بالا به ری اکت میگیم که این کال بک رو فقط یک بار دفعه ی اول اجراش کن مثل componentDidMount.
useEffect(() => { //side effects })
یا
useEffect(() => { //side effects },[dependency])
اگه آرگیومنت دوم رو نزاریم useEffect بعد هر بار رندر اجرا میشه و اگه آرگیومنت دوم رو بزاریم و داخلش یه دپدنسی بدیم فقط وقتایی که اون دپدنسی مقدارش تغییر کنه اینم اجرا میشه مثلا یه استیت به عنوان دپندنسی به آرایه میدیم هر بار که اون استیت تغییر کنه این کال بک اجرا میشه (دفعه ی اول هم این شکل از useEffect اجرا میشه) دقیقا مثل componentDidUpdate.
توی کد بالا ما یک ساید افکت رو داخل کال بک انجام میدیم اما بعدش یه فانکشن هم ریترن میکنیم که به این فانکشنی که توسط کال بک ریترن میشه میگیم clean up و داخل این فانکشن همه ی ساید افکتامون رو کنسل میکنین و یجورایی تمیز میکنیم کال بکمون رو و این فانکشن در دو زمان اجرا میشه ،اول وقتی که کامپوننت حذف میشه مثل componentWillUnmount و دوم وقتی که کامپوننت ری رندر میشه اول میاد این فانکشن رو اجرا میکنه تا ساید افکتای قبلی رو حذف کنه و حالا بعدش ساید افکتای رندر جدید رو اجرا کنه
پس به طور خلاصه فانکشن clean up قبل از ساید افکتای داخل کال بک اجرا میشه تا مسیر رو برای اجرای ساید افکتای جدید تمیز کرده باشه.
هوک useEffect نکات ریز و درشت زیادی داره که در این مقاله نمیگنجه اگه خواستید بیشتر درموردش بدونید میتونید به داکیومنت خود ری اکت مراجعه کنید.
توی هوک قبلی گفتیم که useEffect توی دستکاری دام یکم ضعف داره چون بعد از پینت شدن ui اجرا میشه ، حالا این هوک اومده که اون ضعف رو بپوشونه.
این هوک دقیقا بعد از اجرای رندر و قبل از پینت شدن ui اجرا میشه
ما توی اکثر مواقع از useEffect استفاده میکنیم اما توی این یه مورد ( دستکاری دام) از این هوک استفاده میکنیم
مرورگر ui رو روی صفحه پینت نمیکنه تا این هوک کارش تموم شه پس حواستون باشه که چجوری ازش استفاده میکنید که مشکل پرفورمنس براتون به وجود نیاره همونطور که گفتم اکثر مواقع و برای اکثر کارها همون useEffect کارمون رو راه میندازه.
قبل از اینکه هوک ها ظهور کنن ما از state ها نمیتونستیم توی فانکشنال کامپوننت استفاده کنیم و باید از this.state در کلاس کامپوننت ها استفاده میکردیم، اما الان با این هوک دیگه نیازی به کلاس کامپوننت ها نیست.
const MyState =useState('default value')
مقداری که MyState بهمون میده یه آرایه هستش که شامل دوتا آیتم هستش، آیتم اول مقدار پیشفرض استیت که به عنوان آرگیومنت به هوک useState دادیم هست و آیتم دوم یه فانکشن برای آپدیت این مقدار هستش که باعث میشه اکثر برنامه نویسا موقع استفاده از این هوک ، از Array destructuring استفاده کنن.
اولین مقدار داخل آرایه (state) : اسم استیتِ ماست.
دومین مقدار داخل آرایه ( setState) : اسم فانکشنی که باهاش استیت رو آپدیت میکنیم هستش
میتونیم بجای state و setState هر اسم دیگه ای به این دو بدیم مثل count و setCount و..
آرگیومنتی که به هوک useState دادیم مقدار پیشفرض این استیت هستش که توی عکس بالا یه آبجکته.
یکی از نکاتی که باید بهش توجه کنید اینه که بر موقع استفاده از setState اگه مثلا بخوایم مقدار داخل آبجکت این استیت رو بروزرسانی کنیم و یه پراپرتی جدید به قبلیا اضافه کنیم react متوجه نمیشه که ما قصدمون فقط بروزرسانی هستش نه جایگزینی کل آبجکت،
پس میاد کل ابجکت رو تغییر میده.
توی کد بالا وقتی از setUser استفاده میکنیم نمیاد فقط آبجکت user3 رو به دوتا ی قبلی که به صورت دیفالت تو استیت هستن اضافه و اپدیتش کنه، بلکه میاد کل استیت رو به فقط آبجکت user3 تغییر میده!
واسه جلوگیری از این اتفاق باید اینو بدونید که فانکشن setState یه آرگیومنت میگیره که مقدارش همون مقادیر قبلی داخل استیت هستش و از اون برای بروزرسانی استیت استفاده میکنیم حالا اگه ابجکت یا آرایه باشه با
spread operator (...) یا اگه یه استرینج یا عدد خالی باشه بدون spread operator به شکل زیر انجامش میدیم
از این هوک اغلب برای دوتا کار استفاده میشه:
برای کارایی شماره یک شاید این سوال براتون به وجود بیاد که فرقش با DOM selectors مثل queryselector چیه؟
خب وقتی از DOM selector ها استفاده میکنیم برای پیدا کردن المنت باید کل ساختار درختی DOM رو بگرده تا پیداش کنه درحالی که با استفاده از useRef ما مستقیما آدرس اون المنت رو بهش دادیم و نیازی به پیمایش نداره و این خودش هرچند خیلی کم ولی بازم یه کوچولو تو بهتر کردن پرفورمنس تاثیر مثبت داره و فرق دیگش هم اینه که useRef از چرخه ی زندگی یه کامپوننت باخبره و react میدونه که کی باید مقدارش رو null بده و کی المنت رو بهش پاس بده و در کل وقتی داریم از یه فریمورک یا لایبرری استفاده میکنیم بهتره که از چیزایی که خود اونا میشنهاد میدن استفاده کنیم که حتما یه منفعتی داره.
حالا چجوری نوشته میشه؟
وقتی از useRefاستفاده میکنیم به ما یه ابجکت برمیگردونه که شامل یه پراپرتی به اسم current هستش که داخل اون المنتی که بهش رفرنس دادیم رو نگه میداره البته در ابتدا وقتی که هنوز رفرنسی ندادیم بهش ،مقدار پیشفرضی که به عنوان ارگیومنت به هوک دادیم رو تو current نگه میداره که حالا میتونه null باشه.
برای کارایی شماره دو هم شاید این سوال میش بیاد که تا وقتی state هست چرا باید بخوام یه مقداری رو توی current این هوک نگه دارم که خب فرقش با state اینه که مقداری که به این هوک میدیم تا نگه داره اگه تغییر کنه باعث ری رندر شدن کامپوننت نمیشه درحالی که تغییر مقدتر استیت باعث ری رندر شدن میشه
پس وقتی که مقداری داریم که بدون توجه به لایف سایکلِ کامپوننت ، همیشه در دسترسه و نیازی نیست که تغییرش باعث ری رندر بشه بهتره که توی useRef نگه داریش کنیم.
پس ()createRef چیست؟
این هم فرقش با useRef اینه که با هر بار ری رندر شدن مقدار داخلش دوباره از نو ایجاد میشه اما useRef اینطور نیست و بین ری رندرینگ هم مقدار داخلش رو نگه میداره
اینا از مهمترین هوک هایی بودن که باید بلد میشدین و از زیر سایه کلاس کامپوننت ها خارج میشدین.
دو هوک مهم دیگه useContext و useReducer هستن که بهم مرتبطن و جدا جدا توضیح دادنشون فکر خوبی نیست و همینطور به مبحث state managment مربوط میشن و توی یه پست جدا درموردشون صحبت خواهم کرد.
خسته نباشی ، این مقاله اینجا به پایان میرسه.
خدانگهدار موفق باشی?