ما برای استفاده از دیتا توی کامپوننت ها از props استفاده میکنیم تا بتونیم دیتا رو به کامپوننت ها پاس بدیم
اما وقتی تعداد کامپوننت های تو در تو زیاد بشه استفاده از این روش اصلا پیشنهاد نمیشه و به این شلوغ کاری به اصطلاح prop drilling گفته میشه مثل عکس پایین:
توی عکس بالا ما برای اینکه دیتارو توی فایل textContent استفاده کنیم باید اون دیتارو از تمام پرنت هاش عبور بدیم تا به این برسه
راه حلی که برای این مشکل هست global state management هست که به روش های گوناگون و با ابزار های مختلف میشه پیادش کرد از جمله context api و redux که ما توی این مقاله قراره راجب redux صحبت کنیم
ریداکس یه کتابخونه برای مدیریت کردن استیت های گلوبال هستش که توی کتابخونه و فریمورک هایی مثل ری اکت و انگولار ازش استفاده میشه البته اگه پروژه بزرگ و پیچیده باشه مناسبتره در غیر اینصورت چیزایی مثل context api کفایت میکنه
توی این مقاله قراره هم مفهومات ریداکس رو یاد بگیریم و هم ساختار و نحوه نوشتنش رو (کسایی هستن که مفهومات رو بلدن ولی نمیدونن چطور ریداکس رو پیاده کنن) پس من روند پیاده سازیشو قدم به قدم پیش میبرم و در حین پیش بردن توضیحات لازم رو هم میدم
npm install redux react-redux redux-thunk
از redux برای نوشتن store استفاده میکنیم و از react-redux برای ارتباط گرفتن ری اکت و ریداکس استفاده میشه برای مثال تغییر دادن دیتای توی store و یا خوندن دیتای مربوطه از استیت گلوبال و از redux-thunk هم برای اضافه کردن قابلیت async به اکشن هایی که باید به صورت async باشن استفاده میشه چون در صورت عادی redux به اکشن ها اجازه نمیده به صورت asynchronous نوشته بشن
پوشه redux شامل دو پوشه actions , reducers هست:
پوشه actions شامل یه فایل index هستش که قراره فانکشنهایی رو برای دستور های مختلف توش بنویسیم برای مثال :
همونطور که توی عکس بالا میبینید اکشن در واقع یه فانشکن هستش که برای عملکرد خاصی نوشته میشه و در نتیجه دیتایی رو با یه اسم(type) به خصوصی مخابره(dispatch) میکنه به ردیوسر
توی عکس بالا فانکشن همونطور که از اسمش پیداس برای گرفتن اطلاعات محصول نوشته شده ولی اگه دقت کنیم داره یه فانکشن async بر میگردونه که مابقی کار رو اون انجام میده ! قضیه چیه؟
ما برای استفاده async از اکشن ها نیاز به redux thunk که مارو قادر به نوشتن اکشن async میکنه و نحوه نوشتن اکشن async به شکل بالاس
اما یه اکشن ساده به شکل زیره:
2. پوشه reducers شامل فایل های ردیوسر مختلف برای اکشن های مختلف با اسم های xxxReducer.js (بجای xxxهرچی میتونید بزارید) هستش و یه فایل index به شکل زیر:
ما میتونیم از تک تک فایل های ردیوسر به صورت مستقیم استفاده کنیم و نیازی به ایندکس نداشته باشیم اما برای مرتب تر شدن ما فایل index رو به شکل زیر استفاده میکنیم:
ما با استفاده از combineReducer تمام دیتاهایی که ردیوسر ها برمیگردونن رو توی یه آبجکت جمع میکنیم تا استفاده ازشون خیلی ساده تر باشه
توی عکس بالا ما دیتایی که از ردیوسر productsReducer برگشته رو ریختیم توی پراپرتی products هرجا بخوایم با این اسم میتونیم از دیتا استفاده کنیم
هر فایل ردیوسر هم به شکل زیر هست :
فایل xxxReducer ما شامل یه فانشکن هستش که دوتا پارامتر میگیره اولی state هستش که باید یه مقدار اولیه هم بهش بدید در عکس بالا یه آبجکت خالی هستش و پارامتر دوم action هستش که اگه توی عکسای بالاتر توجه کرده باشید این action در اصل یه آبجکته که از فانکشن اکشن مخابره شده :
{type: 'GET_PRODUCTS_DETAILS' , payload: Product}
داخل فانکشن ما از switchاستفاده میکنیم که اسم اکشن مخابره شده رو ( همون type) رو چک بکنیم و در ازای هر اسمی دیتای به خصوص خودشو ( همون payload) رو برگردونیم و در صورت نبودن هیچ کدوم از اسما همون استیت پیشفرض رو برمیگردونیم و این دیتا توی پراپرتی مخصوص خودش توی آبجکت RootReducerذخیره میکنیم:
حالا این دیتا هر جایی با اسم ProductDetailsدر دسترس هستش
ما برای دسترسی به دیتایی که توسط اکشن ها و ردیوسر ها دست به دست میشن و توی rootReducer قرار میگیرن نیاز داریم تا توی فایل روت کارایی رو انجام میدیم
خب ما مثل عکس بالا توی فایل index باید store رو به وسیله createStore بسازیم که پارامتر اولش rootReducer هست که با combineReducer ساخته شده تا به همه دیتاهایی که ردیوسر ها برمیگردونن یه جا توی یه ابجکت دسترسی داشته باشیم و پارامتر دوم applyMiddleWare هستش که میاد thunk رو به عنوان یه واسط به ریداکس اضافه میکنه تا بتونیم اکشن های async هم انجام بدیم و در آخر با provider دور کامپوننت App که هفت جد و آباد همه ی کامپوننتای دیگس محاصره میکنیم و بهش پراپی میدیم که استور رو دربر داره و حالا هر کامپوننتی داخل app.js هر چقدر هم تو در تو باشه میتونه به صورت مستقیم به هر دیتایی دسترسی داشته باشه بدون اینکه از بالا تا پایین یکی یکی فلان دیتا رو بهش پاس بدیم که در ادامه میگم چطور.
خب لپ کلام بخوام بگم اینطوریه که ما یا میخوایم یه اکشن رو بفرستیم تا دیتا رو تغییر بده و یا میخوایم دیتایی که تغییر کرده رو از ردیوسر بگیریم و توی یو ای نمایش بدیم
ارسال یا مخابره یک دستور(اکشن):
همونطور که تو عکس بالا میبینید ما برای استفاده از هر اکشنی اول اون اکشن رو از redux/actions ایمپورت میکنیم و بعد با استفاده از useDispatch اکشنمون رو مخابره میکنیم.
2. گرفتن دیتا از ردیوسر:
خب اگه یادتون باشه بالا تر توی rootReducer ما دیتایی که از یکی از ردیوسر ها برگشته بود رو روی پراپرتی productDetails ریختیم و توی عکس بالا میبینیم که میتونیم با استفاده از useSelector یه کال بک انجام بدیم که یه پارامتر میگیره که همون rootReducer هستش (تو عکس بالا با اسم state) و از این استیت دقیقا دیتایی که میخوایم رو میگیریم و میریزیم توی متغیر و تو ui نمایشش میدیم به همین سادگی!
توی گیف پایین تموم روند که بالاتر گفتم رو یجا میبینید:
خب اگه تا اینجا خوندی و خسته نشدی بیا تا یه اموزش کوچیک هم در ادامه بهت بدم اونم استفاده از redux persist هستش که برای استفاده ازش فقط کافیه یه کوچولو فایل src/index.js رو تغییر بدیم اما اصلا redux persist چی هستش؟
مطمعنا خیلیاتون دلتون میخواد دیتایی که هر سری اپدیت میکنید رو نگه دارید و طوری نباشه که با یه رفرش همش بپره!
خب این پکیج دقیقا برای همینه که میاد هر دیتارو که از ردیوسر میگیره و توی لوکال استوریج ذخیره میکنه تا با رفرش کردن اون دیتا نپرن!
برای استفاده ازش اول اینطوری نصبش کنید:
npm install redux-persist
بعدش فایل روت رو بجای اون تغییراتی که بالاتر گفتم اینطوری بزارید :
چیزایی که لازمه رو طبق عکس بالا از Redux persist ایمپورت میکنیم.
آبجکت persistConfig میاد تنظیم میکنه که دقیقا چیو چجوری سیو کنه تو لوکال مثلا ردیوسری داریم که نمیخوایم توی لوکال ذخیره بشه دیتاش و با هر رفرش ناپدید شه از پراپرتی blackList که آرایه هست استفاده میکنیم و اسمی که توی RootReducer به این ردیوسر دادیم رو به صورت استرینج توی این آرایه قرار میدیم.
متغیر persistedReducer میاد قبل از استور rootReducer رو میگیره و ذخیره میکنه و حالا به Store به عنوان پارامتر اول بجای rootReducer میایم متغیر persistedReducer رو پاس میدیم که با هر رفرش خالی نکنه دیتا رو ما باید App رو علاوه بر provider با PersistGate هم بپوشونیم که که متغیر persistor هم حکم Store برای PersistGate رو داره و loading هم پراپی هستش که میدیم تا لود شدن دیتا بیاد و اونو نمایش بده مثلا : laoding={<Loading />} .
فقط حواستون باشه چه مقدار دیتا و چه دیتایی توی لوکال ذخیره میکنید چون هم فضاش محدوده و هم میتونه دیتایی باشه که نخواید توی لوکال استوریج ذخیره شه
خب این مقاله اینجا تموم شد و دیدیم که ریداکس همچین غول زشت و بی شاخ و دمی هم که ازش میترسن نیست و برعکس خیلی هم عالیه :)
امیدوارم خسته نشده باشی و بدردت خورده باشه
خدانگهدار موفق باشی?