خب خب قبل شروع بزار بگم که با خوندن این مقاله قراره چی نصیبت بشه
توی این مقاله کل lifecycle یا چرخه زندگی رو قراره زیر و رو کنیم و با مثالای خیلی تمیز سعی میکنیم زمان وقوع هر متد و نحوه نوشتن و سینتکس متد های lifecycle رو و به بیان دیگه قراره کل جد و آباد متد های چرخه ی زندگی رو بیاریم وسط! بریم که رفتیم
اگه بخوام خودتو مثال بزنم ، تو توی طول زندگیت یه چرخه ای رو دنبال میکنی که مطمعنن میتونی حدس بزنی این چرخه همون چرخه ی زندگی هستش ، قبل اینکه به دنیا بیای احتمالا برات اسم و دین و.. انتخاب کردن و اسم پدر و مادرت و... مشخصه (initialization) ، توی مرحله بعدی تو به دنیا میای ( mounting ) ، مرحله بعدی
مرحله ی بزرگ شدن و تغییر کردنت هستش ( updating ) و مرحله ی آخر مثل هر چرخه ی زندگی ای به مرگ و پایان ختم میشه ( unmounting ).
این یه مثال ساده و مختصر از چرخه ی زندگی بود که توی همه چی به همین شکل جریان داره و کامپوننت های ری اکت هم از این قضیه مستثنی نیستند. حالا قراره در عین حال که این مراحل و متد هاشو در ادامه توضیح میدم برای مثال هاشون از همین مثال بالا استفاده کنم.
توی این مرحله استیت ها و هرچی که نیازشه رو مقداردهی اولیه میکنیم
توی این مرحله متد render اجرا میشه و کامپوننت به وجود میاد
توی این مرحله کامپوننت با پراپ ها و استیت هاش رابطه مستقیم داره که باعث تغییرش میشن.
چطور؟
اگه یه سنگ به سمت صورتت پرت کنن چی میشه؟ چون اون تیکه از صورتت که قبلا زخم نبود زخم میشه درسته؟ پس یه تغییری کردی به این میگن اپدیت شدن.
حالا اگه همون سنگ به همون شکل و با همون سرعت پرت شه و به همون نقطه از صورتت بخوره تو تغییری نمیکنی چون اون زخم از قبل اونجا هست و اون نوع سنگ و نحوه و سرعت پرتابش و محل برخوردش هیچ تغییری نکرده که باعث تغییر خاصی در تو بشه اما اگه دفعه ی بعد اون سنگه بزرگتر باشه جای زخمشم بزرگتر خواهد بود و تو باز تغییر خواهی کرد ( مطمعنم مثالای بهتری الان توی سرت هست و من با زدن همچین مثالایی فقط سعی میکنم طوری بگم که این مرحله از چرخه رو درست درک کنی. فقط امیدوارم با این مثالا تا اخر این مقاله به کشتن نداده باشمت =)))) )
پس نتیجه گرفتیم که این سنگه همون پراپ هستش و تو همون کامپوننت هستی اگه پراپی که به سمت کامپوننت میندازن تغییر کنه همین باعث تغییر کامپوننت هم میشه و در غیر اینصورت چیزی نباید تغییر بکنه. جلوتر بیشتر از جزییاتش حرف میزنم فلن تا اینجا واسه این بسه.
توی این مرحله با یه کلیک به صفحه ی دیگه یا حالا با یه رویداد خاصی دیگه به این کامپوننت نیازی نیست و باید حذف بشه
دیگه مثالشو تو زندگی خودمون میتونی حدس بزنی.
1. مرحله ی initialization که چیزی نداره و فقط شامل همون constructor و super و setState هستش.
2. مرحله ی mounting :
componentWillMount(){ //code }
این متد فقط بار اول و قبل از متد render اجرا میشه ینی قبل از به وجود اومدن کامپوننت و داخلش میتونی تصمیم بگیری که قبل از به وجود اومدن کامپوننت چه اتفاقی بیفته
توجه: این متد از سال 2018 به بعد منقضی شد و فقط تا ورژن 17 ری اکت میشه ازش استفاده کرد و بعد از اون بهتره که یا از روش های جایگزین استفاده کنی به اسمش کلمه ی _UNSAFE رو اضافه کنی
دلیل انقضا : ری اکت دید که وقتی توی این متد عملیات Asynchronous مثل data fetching انجام میدیم باعث ری رندر شدن بیش از یکبار کامپوننت و ایجاد تداخل میشه ، چرا؟ چون این متد باید قبل از متد رندر اجرا بشه ولی کد غیر همزمان داخلش هم باید بعد از متد رندر اجرا بشه چون همونطور که تو مقاله قبلی توضیح دادم متد رندر که synchronous هستش اجرا شدنش مقدم هست بر توابع asynchronous و همین باعث تداخل میشه
جایگزین هاش چی هستن؟
برای عملیات asynchronous بهتره از componentDidMount استفاده کرد و برای عملیات غیر همزمان میتونی از همین متد UNSAFE_componentWillMount استفاده کنی که البته پیشنهاد نمیشه یا ام که تو همون Constructor کارتو راه بندازی.
componentDidMount(){ // code }
این متد فقط بار اول و بعد از متد render اجرا میشه (وقتی میگم بعد از متد render منظورم اینه که بعد از اینکه کامپوننت به وجود میاد و میره رو صفحه).
توی این متد میتونی یه بلایی سر کامپوننت بعد از اینکه به وجود میاد و میره روی صفحه بیاری ، میتونی عملیات asynchronous انجام بدی.
3. مرحله updating:
shouldComponentUpdate(newProps,newState){ //اگه پراپی که گرفتیم با اینی که از قبل داریم فرق داشته باشه این متد به ما ترو میده در غیر اینصورت فالس میده
newProps.value !== this.props.value
}
این متد دفعه ی اول اجرا نمیشه و از دفعات بعد، قبل هر ری رندر اجرا میشه .
یادتونه بالاتر مثال پرتاب سنگ به صورت رو برای اپدیت شدن زدم؟ خب یه جای کار با مثالی که زدم فرق داره اونم اینه که توی ری اکت حتی اگه پراپ تغییری نکرده باشه بازم باعث میشه جهت محکم کاری اپدیت (re-render ) بشه اونم بخاطر اینه که این متد ( shouldComponentUpdate ) به طور پیش فرض true برمیگردونه و همین true ، باعث re-render شدن میشه . در کل از این متد برای جلوگیری از این اتفاق ( re-render شدن الکی) استفاده میشه که فقط وقتی پراپ متفاوت بود ری رندر بشه که در نتیجه باعث بالا رفتن سرعت سایتمون میشه. فقط کافیه ( nextProps.value !== this.props.value ) رو بزارید داخل متد تا دیگه سر خود هر سری true برنگردونه.
توجه: اگه این متد false برگردونه مانع اجرا شدن متد های render و componentWillUpdate و componentDidUpdate میشه.
componentWillUpdate(newProps,newState){
// code اگه متد بالایی ترو برگردونه باشه این متد اجرا میشه
}
این متد هم دفعه ی اول اجرا نمیشه و از دفعات بعد، قبل هر ری رندر اجرا میشه و توش میشه قبل از اپدیت شدن کامپوننت یه بلایی سرش آورد و دستکاریش کرد.
توجه: این متد از ورژن 16.6 به بعد ری اکت منقضی شد و فقط تا ورژن 17 ری اکت میشه ازش استفاده کرد و بعد از اون بهتره که یا از روش های جایگزین استفاده کنی به اسمش کلمه ی _UNSAFE رو اضافه کنی.
دلیل انقضا: از ورژن 16.6 به بعد ری اکت یه قابلیتی آورد به اسم suspense , lazy react component که کارشون اینه که متد render رو از synchronous به asynchronous تبدیل و رندر شدن یه کامپوننت رو به تاخیر بندازن که باعث پرفورمنس بهتر میشه اما این قابلیت زد خااره این متد ( componentWillUpdate ) رو تار کرد ، چطور؟!
غیرهمزمان شدن متد render باعث تداخل بین این متد و componentWillUpdate میشه چون تو هر بلایی که سر dom بخوای بیاری یا یه مقداریشو بگیری باید صبر کنه تا Dom بالا اول بیاد.
جایگزین هاش چی هستند؟
یا از همین متد UNSAFE_componentWillUpdate باید استفاده کرد که اصلا پیشنهاد نمیشه یا از یه متد جدید بعد از این معرفیش میکنم.
getSnapshotBeforeUpdate(prevProps,PrevState){
//code
}
این متد قبل از re-render و اپدیت شدن اتفاق میفته و میاد یه سری اطلاعات رو از همین کامپوننتی که هنوز اپدیت نشده میچینه و نگهش میداره که شاید بدردمون بخوره...
این اطلاعاتی که چیده رو ریترن میکنه اما خب مقدارش رو کجا میتونیم استفاده بکنیم؟
مقداری که ریترن میکنه به عنوان ارگومان سوم پاس داده میشه به متد componentDidUpdate که بعد از این معرفیش میکنم.
همونطور که بالاتر گفتم این یه متد هستش که جایگزین componentWillUpdate شده و شاید سوال براتون پیش بیاد که این با رندر asynchronous مشکلی نداره؟
خب باید بگم نه چون این قرار نیست از کامپوننتی که هنوز لود نشده اطلاعات بگیره که بخاطرش هم بخواد واسته ، این قراره از کامپوننت ورژن قبلی این اطلاعات رو بگیره که همه چی توش موجوده و هنوز اپدیت نشده.
شاید وقتی اولین بار اینو میخونی فک کنی این دوتا کاراییشون فرق دارن و احمقانس این رو جایگزین برای اون دونسته باشن اما وقتی باهاش کار کنید میبینید هرکاری با منقضیا میکردید با همین جایگزیناشونم میتونید بکنید( این جایگزین هارو خود ری اکت پیشنهاد کرده ).
فقط دوتا متد موند رفیق، بیا تمومش کنیم.
componentDidUpdate(prevProps,prevState,Snapshot){
if( prevProps.value !== this.props.value){
// code یادتون نره کداتون رو داخل این شرط اجرا کنید تا به خطای حلقه ی بینهایت نخورید
}
}
این متد بار اول اجرا نمیشه و فقط بعد از re-render و اپدیت شدن اجرا میشه و همونطور که میبینید مقداری که توی متد بالا (getSnapshotBeforeUpdate ) ریترن شده اینجا میتونیم ازش استفاده کنیم (Snapshot)
4. مرحله Unmounting :
componentWillUnmount(){
//clean up
}
خب این تنها متد برای این مرحله هستش.
وقتی یه کامپوننت داره حذف میشه این متد اجرا میشه و در حقیقت کارش اینه که هر چی network request و تایمر و در کل هر چی که در طول حیات این کامپوننت داره اجرا میشه رو کنسل میکنه تا در نبود این کامپوننت این request ها هم الکی اجرا نشن و سرعت سایت بره بالاتر.
بلخره تموم شد، اینم فلوچارت این متد ها که بتونی ترتیب اجرا شدنشون رو درک کنی و بهتر استفادشون کنی:
این متد ها و نحوه و زمان کارکردشون از مباحث مهمی بود که باید یاد میگرفتی هرچند که الان با وجود فانکشنال کامپوننت و هوک ها و... که در مقاله های آینده راجبشون حرف خواهم زد، کمتر مزاحم این عزیزان میشیم.
خسته نباشی و ممنون که تا آخر با حوصله این مقاله رو خوندی.
خدانگهدار?