ریداکس چیست؟ — معرفی کتابخانه Redux به زبان ساده
در این نوشتار به معرفی کتابخانه Redux پرداختهایم و میخواهیم بدانیم ریداکس چیست و چگونه میتوانیم به شکلی صحیح از کتابخانه Redux برای توسعه برنامههای خود بهره ببریم. مفاهیم و اصطلاحات کلیدی و ضروری را برای استفاده از ریداکس پوشش دادهایم و همچنین به برخی از سوالات پرتکرار پاسخ داده شده است.
ریداکس چیست ؟
ریداکس یک الگو و کتابخانه برای مدیریت و بهروزرسانی «وضعیت» (State) برنامه با استفاده از رویدادهایی به نام Action است. ریداکس، یک «انباره» (Store) متمرکز برای State محسوب میشود که در سراسر برنامه مورد استفاده قرار میگیرد و دارای قوانینی است که تضمین میکنند State به صورت قابل پیشبینی بهروزرسانی شود.
پیش از ادامه این مبحث لازم است یادآور شویم که میتوانید ریداکس را با استفاده از مجموعه آموزش رداکس Redux فرادرس یاد بگیرید. برای آشنایی بیشتر با اینکه ریداکس چیست در ادامه به این موضوع میپردازیم که چرا و چه زمانی از ریداکس استفاده میکنیم.
علت استفاده از ریداکس چیست ؟
ریداکس به شما کمک می کند تا «وضعیت سراسری» (Global State) را مدیریت کنید. Global State نوعی State است که در بسیاری از بخشهای برنامه بهکار میرود. الگوها و ابزارهای ارائه شده توسط کتابخانه Redux، درک زمان، مکان، چرایی و نحوه بهروزرسانی State برنامه و نحوه رفتار منطق برنامه در هنگام وقوع این تغییرات را آسانتر میکند. ریداکس، ما را به سمت نوشتن کدهایی هدایت میکند که قابل پیشبینی و قابل تست باشد و به ما اطمینان میدهد برنامه همانطوری کار خواهد کرد که انتظار میرود.
چه زمانی باید از ریداکس استفاده کنیم؟
ریداکس به ما کمک میکند تا State اشتراکی (Shared State) را مدیریت کنیم، اما مانند هر ابزار دیگری، در استفاده از ریداکس باید برخی موازنهها را در نظر داشته باشیم. در استفاده از کتابخانه Redux مفاهیم بیشتری برای یادگیری و کدهای بیشتری برای نوشتن وجود خواهد داشت. ریداکس تا حدی موجب جهتگیری غیرمستقیم کدها میشود و توسعهدهنده را ملزم میسازد که برخی محدودیتها و قیدها را در نظر بگیرد. بنابراین برای استفاده از کتابخانه Redux باید موازنه بهرهوری کوتاهمدت و بلندمدت را در نظر داشته باشیم. بهتر است ریداکس در موقعیتهای زیر مورد استفاده قرار گیرد:
- زمانی که برنامه دارای تعداد زیادی State باشد و این Stateها مکررا در طول برنامه مورد استفاده قرار بگیرند.
- State برنامه مکررا بهروزرسانی میشود.
- وقتی که منطق بهروزرسانی State پیچیده باشد.
- در صورتی که برنامه دارای یک پایگاه کد متوسط یا بزرگ باشد که افراد زیادی روی آن کار میکنند.
پیش نیاز یادگیری ریداکس چیست ؟
برای درک بهتر پاسخ سوال ریداکس چیست لازم است بدانیم چه پیشنیازهایی برای یادگیری ریداکس نیاز داریم. بنابراین، در ادامه به ارائه فهرستی از پیشنیازهای یادگیری ریداکس پرداخته شده است.
- HTML و CSS
- سینتکس و امکانات ES6
- اصطلاحات تخصصی React شامل:
- JSX
- State
- Function Components
- Props
- Hooks
- جاوا اسکریپت ناهمگام (Asynchronous) و ارسال درخواست های AJAX.
اگر از قبل با این موضوعات آشنا نیستید، توصیه میکنیم آشنایی لازم را کسب و سپس بر یادگیری ریداکس تمرکز کنید. در ابتدا بهتر است افزونههای DevTools مربوط به ریاکت و ریداکس را در مرورگر خود نصب کنید.
کتابخانه ها و ابزار ریداکس چیست ؟
Redux یک کتابخانه جاوا اسکریپت به حساب میآید. با این حال، خود معمولاً حاوی چندین بسته دیگر است. در ادامه به برخی از این ابزارها اشاره شده است.
کتابخانه React Redux چیست ؟
ریداکس میتواند با هر چارچوب UI یکپارچه شود اما بیشتر با React مورد استفاده قرار میگیرد. React Redux یک بسته رسمی است که برای بهروزرسانی انباره، به کامپوننتهای React اجازه میدهد با خواندن بخشهایی از State و ارسال کردن (Dispatch) اکشنها، با آن انباره تعامل داشته باشند.
Redux Toolkit یا جعبه ابزار ریداکس چیست ؟
این جعبه ابزار رویکرد پیشنهادی برای نوشتن منطق ریداکس است که شامل بستهها و تابعهایی میشود که برای ساختن یک برنامه ریداکس ضروری هستند. Redux Toolkit عمده وظایف ریداکس را ساده میکند، از اشتباهات رایج جلوگیری میکند و نوشتن برنامههای ریداکس را آسانتر میکند.
افزونه Redux DevTools چیست ؟
افزونه Redux DevTools تاریخچهای از تغییرات State موجود در انباره ریداکس را در طول زمان نشان میدهد. این افزونه به شما امکان میدهد برنامههای خود را با استفاده از تکنیکهای قدرتمندی مانند «اشکال زدایی در طول زمان» (Time-Travel Debugging) به طور موثر اشکالزدایی کنید.
معرفی فیلم های آموزش جاوا اسکریپت
فرادرس دورههای آموزشی را بر اساس موضوع دستهبندی و در قالب مجموعههای آموزشی ارائه میکند. مجموعه آموزشی اختصاصی و جامع برنامهنویسی جاوا اسکریپت نیز در فرادرس موجود است. در این صفحه، همه دورههای آموزشی مرتبط با برنامهنویسی جاوا اسکریپت گردآوری شدهاند. زبان برنامهنویسی جاوا اسکریپت و فریمورکهای وابسته به آن به سرعت در حال فراگیر شدن در دنیای وب هستند. یادگیری این کتابخانهها و فریمورکها، پیشنیاز مهمی برای ورود به بازار کار برنامهنویسی سمت کاربر و سرور محسوب میشود. در تصویر فوق تنها تعداد محدودی از دورههای آموزشی این مجموعه نشان داده شدهاند.
- برای شروع یادگیری برنامهنویسی فریمورکهای جاوا اسکریپت + اینجا کلیک کنید.
اصطلاحات رایج در ریداکس چیست ؟
برای استفاده از کتابخانه Redux باید با برخی مفاهیم و اصطلاحات آشنا شویم که اینجا فهرست شدهاند و در ادامه نیز هر یک از آنها شرح داده میشوند و مثالهایی هم برایشان ارائه شده است.
- مدیریت State
- تغییر ناپذیری
- Action برای بهروزرسانی State
- متد «سازنده اکشن» (Action Creator)
- متد Reducer
- انباره Store
- متد Dispatch
- تابع Selector
مدیریت State در ریداکس چیست ؟
برای تشریح مفهوم مدیریت State، به عنوان مثال، کامپوننتی به نام Counter با استفاده از ریاکت توسعه داده شده است که قطعه کد آن را در ادامه ملاحظه میکنید. این کامپوننت یک عدد را در State در نظر میگیرد و با کلیک کاربر بر یک دکمه، آن عدد را افزایش میدهد.
1function Counter() {
2// State: a counter value
3const [counter, setCounter] = useState(0)
4
5// Action: code that causes an update to the state when something happens
6const increment = () => {
7setCounter(prevCounter => prevCounter + 1)
8}
9
10// View: the UI definition
11return (
12<div>
13Value: {counter} <button onClick={increment}>Increment</button>
14</div>
15)
16}
این قطعه کد، برنامهای مستقل (Self-Contained App) است که شامل بخشهای زیر میشود:
- State: شیئی جاوا اسکریپتی است که دادههای پویای کامپوننت را نگهداری میکند. تمامی Stateهای برنامه داخل یک شی درختی به نام Store ذخیره میشوند که در اصطلاح به آن «منبع حقیقت واحد» (Single Source of Truth) یا به اختصار SSOT گفته میشود.
- View: توصیف UI بر اساس State جاری است.
- Action: رویدادی که بر اساس ورودی کاربر در برنامه اتفاق میافتد و موجب بهروزرسانی State میشود.
جریان داده یک طرفه در ریداکس چیست ؟
معماری Redux حول یک جریان داده یکطرفه دقیق میچرخد. این بدان معناست که تمام دادههای یک برنامه از الگوی چرخه عمر یکسانی پیروی میکنند که منطق برنامه شما را قابل پیشبینیتر میسازد و درک آن را آسانتر میکند.
- State وضعیت برنامه را در یک نقطه خاص از زمان توصیف میکند.
- UI بر اساس آن State، رندر میشود.
- وقتی رویدادی اتفاق میافتد، مانند موقعی که کاربر روی یک دکمه کلیک میکند، State بر اساس آنچه بهروزرسانی میشود که رخ داده است.
- UI بر اساس State جدید «دوباره رندر» (Re-Render) میشود.
توجه داشته باشید اگر ما چندین کامپوننت داشته باشیم که نیاز به اشتراکگذاری و استفاده از یک State را داشته باشند، امکان دارد سادگی از بین برود، به خصوص اگر آن کامپوننتها در قسمتهای مختلف برنامه قرار داشته باشند. گاهی اوقات میتوان این مسئله را با «بالا کشیدن وضعیت» (Lifting State Up) به کامپوننت والد حل کرد، اما این همیشه کمکی نمیکند. یکی از راهحلهای این مسئله، استخراج State به اشتراک گذاشته شده و قرار دادن آن در یک مکان متمرکز خارج از درخت کامپوننت است.
با این کار، درخت کامپوننت ما به یک View بزرگ تبدیل میشود و هر کامپوننتی صرف نظر از اینکه در کجای درخت قرار دارد، میتواند به State دسترسی داشته باشد یا Action خود را ارسال کند. با تعریف و تفکیک مفاهیم مربوط به مدیریت State و اجرای قوانینی که استقلال بین Viewها و Stateها را حفظ میکند، به کدهای خود قابلیت نگهداری و ساختارمندی بیشتری میدهیم.
ایده اصلی ریداکس در واقع شامل یک مکان متمرکز یکتا برای نگهداری Global State در برنامه است. ایده ریداکس همچنین شامل الگوهای خاصی است که باید هنگام بهروزرسانی آن State در نظر گرفته شود بهطوری که کد قابل پیش بینی باشد.
تغییر ناپذیری در ریداکس چیست ؟
اصطلاح "Mutable" به معنای «تغییرپذیر | قابل جهش» است. در برنامهنوسی اگر چیزی «تغییر ناپذیر» (Immutable) باشد، هرگز نمیتوان محتوای آن را تغییر داد. اشیا و آرایههای جاوا اسکریپت همه به طور پیشفرض تغییرپذیر هستند. یعنی اگر یک شی ایجاد کنیم، میتوانیم محتوای فیلدهای آن را تغییر دهیم یا اگر آرایهای ایجاد کنیم، میتوانیم محتویات آن را تغییر دهیم. برای درک بهتر این موضوع در ادامه مثالی آمده است.
1const obj = { a: 1, b: 2 }
2// still the same object outside, but the contents have changed
3obj.b = 3
4
5const arr = ['a', 'b']
6// In the same way, we can change the contents of this array
7arr.push('c')
8arr[1] = 'd'
به این جهش، تغییر شی یا تغییر آرایه گفته میشود. این همان شی یا آرایه مرجع در حافظه به حساب میآید، اما اکنون محتوای داخل آن شی تغییر کرده است. به منظور بهروزرسانی غیرقابل تغییر مقادیر، کد در ابتدا باید از اشیاء/آرایههای موجود نسخه کپی شدهای را تهیه کند و سپس آن را تغییر دهد.
ما میتوانیم این کار را به صورت دستی با استفاده از عملگر Spread در جاوا اسکریپت و همچنین متدهای آرایه انجام دهیم. این عملیات، آرایه را تغییر نمیدهند بلکه نسخه کپیشده را برمیگردانند.
1const obj = {
2a: {
3// To safely update obj.a.c, we have to copy each piece
4c: 3
5},
6b: 2
7}
8
9const obj2 = {
10// copy obj
11...obj,
12// overwrite a
13a: {
14// copy obj.a
15...obj.a,
16// overwrite c
17c: 42
18}
19}
20
21const arr = ['a', 'b']
22// Create a new copy of arr, with "c" appended to the end
23const arr2 = arr.concat('c')
24
25// or, we can make a copy of the original array:
26const arr3 = arr.slice()
27// and mutate the copy:
28arr3.push('c')
ریداکس انتظار دارد که همه بهروزرسانیهای State بهطور تغییرناپذیر انجام شوند. ما به اهمیت این موضوع کمی بعدتر خواهیم پرداخت. همچنین راههای سادهتر برای نوشتن منطق بهروزرسانی تغییرناپذیر را بررسی خواهیم کرد.
Action چگونه موجب بهروزرسانی State می شود ؟
اکشن شی ساده جاوا اسکریپتی محسوب میشود که دارای یک فیلدtype است. میتوان Action را به عنوان رویدادی در برنامه در نظر گرفت که اتفاق رخ داده شده را توصیف میکند. فیلدtypeباید رشتهای باشد و به Action یک نام توصیفی مانند"todos/todoAdded" بدهد. ما معمولاً آن رشته را بهشکل"domain/eventName" مینویسیم. بخش اول این رشته ویژگی یا دستهای است که این Action به آن تعلق دارد و قسمت دوم، همان چیزی است که اتفاق میافتد. یک شی اکشن میتواند حاوی فیلدهای دیگری با اطلاعات اضافی درباره آنچه باشد که اتفاق افتاده است. طبق قرارداد، ما آن اطلاعات را در فیلدی به نامpayload قرار میدهیم. یک شی اکشن در حالت کلی به شکل زیر است:
1const addTodoAction = {
2type: 'todos/todoAdded',
3payload: 'Buy milk'
4}
متد سازنده اکشن چه وظیفهای دارد ؟
«سازنده اکشن» (Action Creator) تابعی است که یک شی اکشن را ایجاد میکند و برمیگرداند. ما معمولاً از این تابع استفاده میکنیم تا مجبور نباشیم هر بار شیء Action را به صورت دستی بنویسیم:
1const addTodo = text => {
2return {
3type: 'todos/todoAdded',
4payload: text
5}
6}
Reducer در ریداکس چه عملی انجام میدهد ؟
Reducer تابعی است کهstate جاری و یک شیaction را دریافت میکند و سپس تصمیم میگیرد که در صورت لزوم چگونه State را بهروز کند و در نهایت State جدید را به شکل(state, action) => newStateبرمیگرداند. میتوان یک Reducer را به عنوان شنونده رویداد در نظر گرفت. شنوندهای که رویدادها را بر اساس نوع Action (رویداد) دریافت شده مدیریت میکند.
قوانین Reducer
تابعهای Reducer به این دلیل نامگذاری میشوند که شبیه به «توابع فراخوانی مجدد» یا همان Callback Functionهایی هستند که به متدArray.reduce() ارسال میشوند. Reducerها همیشه باید از قوانین خاصی پیروی کنند:
- آنها فقط باید مقدار State جدید را بر اساس آرگومانهایstateوaction محاسبه کنند.
- آنها مجاز به تغییرstateموجود نیستند. در عوض، آنها باید با کپی کردنstateموجود و ایجاد تغییرات در مقادیر کپی شده، بهروزرسانیهای تغییرناپذیر را انجام دهند.
- آنها نباید:
- هیچ منطق ناهمگامی (Asynchronous) را انجام دهند،
- مقادیر تصادفی را محاسبه کنند، یا
- «اثرات جانبی» (Side Effects) ایجاد کنند.
منطق Reducer
تابع Reducer حاوی منطق State است. این تابع دو آرگومان State جاری و شی Action را میگیرد و در خروجی، State بعدی را برمیگرداند. منطق درون تابعهای Reducer معمولاً از الگوی زیر پیروی میکند:
- بررسی میکند که آیا Reducer، اکشن را درنظر میگیرد یا خیر.
- اگر بله، یک کپی از State تهیه میکند، کپی را با مقادیر جدید بهروزرسانی میکند و آن را در خروجی برمیگرداند.
- در غیر این صورت، State موجود را بدون تغییر در خروجی برمیگرداند.
مثالی برای شرح مراحل لازم برای Reducer
در اینجا مثال سادهای برای توضیح مراحلی ارائه شده است که هر Reducer باید درنظر داشته باشد.
1const initialState = { value: 0 }
2
3function counterReducer(state = initialState, action) {
4// Check to see if the reducer cares about this action
5if (action.type === 'counter/increment') {
6// If so, make a copy of `state`
7return {
8...state,
9// and update the copy with the new value
10value: state.value + 1
11}
12}
13// otherwise return the existing state unchanged
14return state
15}
Reducerها میتوانند از هر نوع منطقی شامل switch ،if/else، حلقهها و غیره، برای تصمیمگیری در مورد State جدید استفاده کنند.
Store در ریداکس چیست و چه نقشی ایفا میکند ؟
State جاری برنامه در شیئی به نام Store جای میگیرد. Store با ارسال یک Reducer ایجاد میشود و متدی به نامgetState() دارد که مقدار State جاری را برمیگرداند.
1import { configureStore } from '@reduxjs/toolkit'
2
3const store = configureStore({ reducer: counterReducer })
4
5console.log(store.getState())
6// {value: 0}
متد Dispatch در ریداکس چه کارکردی دارد ؟
Store در ریداکس متدی به نام dispatch دارد. تنها راه برای بهروزرسانی State، فراخوانی کردنstore.dispatch() و ارسال یک شی اکشن است. Store تابع Reducer خود را اجرا و مقدار State جدید را ذخیره میکند و میتوان با فراخوانیgetState() مقدار State را بازیابی و بهروزرسانی کرد.
1store.dispatch({ type: 'counter/increment' })
2
3console.log(store.getState())
4// {value: 1}
میتوان ارسال Action را بهعنوان «رویداد» در برنامه در نظر گرفت. یعنی رویدادی اتفاق افتاده است و ما میخواهیم Store در مورد آن آگاه شود. Reducerها مانند شنوندگان رویداد عمل میکنند و وقتی Action مورد نظرشان را میشنوند، در پاسخ، State را بهروزرسانی میکنند. ما معمولاً Action Creatorها را فراخوانی میکنیم تا اکشن به درستی ارسال شود.
1const increment = () => {
2return {
3type: 'counter/increment'
4}
5}
6
7store.dispatch(increment())
8
9console.log(store.getState())
10// {value: 2}
تابع Selector در ریداکس چه وظیفهای دارد ؟
Selectorها تابعهایی هستند که میدانند چگونه قطعه اطلاعات خاصی را از مقادیر Store استخراج کنند. همانطور که یک برنامه بزرگتر میشود، این کارکرد میتواند به جلوگیری از تکرار منطق کمک کند، زیرا بخشهای مختلف برنامه نیازمند خواندن دادههای یکسان هستند.
1const selectCounterValue = state => state.value
2
3const currentValue = selectCounterValue(store.getState())
4console.log(currentValue)
5// 2
جریان داده در ریداکس
پیشتر در مورد «جریان داده یکطرفه» بحث شد؛ اما به طور خاص برای ریداکس، میتوانیم این مراحل را با جزئیات بیشتری بسط دهیم:
- راه اندازی اولیه:
- یک Store با استفاده از تابع Reducer ریشه ایجاد میشود.
- State یک بار Reducer ریشه را فراخوانی میکند و مقدار بازگشت داده شده را به عنوانstate اولیه ذخیره میکند.
- هنگامی که UI برای اولین بار دوباره رندر میشود، کامپوننتهای UI به State جاری Store دسترسی پیدا میکنند و از آن دادهها استفاده میکنند تا در مورد رندر تصمیم بگیرند. کامپوننتهای UI همچنین برای آگاهی یافتن از بهروزرسانیهای Store مشترک میشوند (Subscribe میکنند) و به این ترتیب از تغییر احتمالی State مطلع میشوند.
- بهروزرسانیها:
- رویدادی در برنامه رخ میدهد، مثلاً کاربر روی دکمهای کلیک میکند.
- کد برنامه اکشنی را مثلا به این شکل زیر به Store ارسال میکند. dispatch({type: 'counter/increment'})
- Store، تابع Reducer را دوباره باstate قبلی وaction جاری اجرا میکند و مقدار بازگشتدادهشده را به عنوانstateجدید ذخیره میکند.
- Store، بهروزرسانی Store را به تمام قسمتهای رابط کاربری اطلاعرسانی میکند که در آن مشترک شدهاند.
- هر کامپوننت رابط کاربری که به دادههایی از Store نیاز دارد، بررسی میکند که آیا بخشهای State مورد نیاز تغییر کردهاند یا خیر.
- هر کامپوننتی که دادههای خود را تغییر میدهد، باید دوباره رندر شود و بنابراین آنچه که روی صفحه نمایش داده میشود بهروزرسانی خواهد شد.
در تصویر متحرک زیر جریان داده در کتابخانه Redux را ملاحظه میکنید.
سوالات رایج و پرتکرار ریداکس
در ادامه به تعدادی از سوالات رایج و پرتکرار در مورد ریداکس پرداخته شده است تا بتوان به اندازه کافی ابهامات را در این خصوص برطرف کرد.
آیا Redux فقط با React قابل استفاده است؟
Redux می تواند به عنوان انباره اطلاعات برای هر لایه از UI استفاده شود. استفاده رایج ریداکس با React و React Native همراه است، اما امکان ارتباط ریداکس با Vue.js و Angular و موارد دیگر وجود دارد. Redux صرفا یک ساز و کار «اشتراک» (عضویت | Subscription) را ارائه میدهد که میتواند توسط هر کد دیگری استفاده شود.
با این اوصاف، زمانی ریداکس بسیار مفید است که با پیادهسازی Declarative View ترکیب میشود و میتواند بهروزرسانیهای UI را از تغییرات State، استنتاج کند. پیادهسازی Declarative View در React یا یکی از کتابخانههای مشابه موجود بهکار میرود.
آیا به منظور استفاده از ریداکس باید ابزار خاصی برای Build کردن داشته باشیم؟
ریداکس در اصل به کمک ES6 نوشته شده و برای تولید با Webpack و Babel به ES5 منتقل شده است. باید بتوان بدون توجه به فرآیند Build جاوا اسکریپت از آن استفاده کرد. Redux همچنین یک UMD Build ارائه میدهد که میتواند مستقیماً بدون هیچگونه فرآیند Build، مورد استفاده قرار گیرد.
آیا باید تمام State خود را در Redux قرار دهیم؟ در چه مواقعی باید از setState() استفاده کنیم؟
هیچ پاسخ درستی برای این سوال وجود ندارد. برخی از کاربران ترجیح میدهند به جای نگهداری یک نسخه کاملا سریالی و کنترلشده از برنامه خود، تک تک دادهها را در ریداکس نگه دارند. برخی دیگر ترجیح میدهند Non-Critical State و یا UI State را در داخل State داخلی یک کامپوننت حفظ کنند. استفاده از State کامپوننت محلی مفید است. بهعنوان یک توسعهدهنده، وظیفه شما این است که تعیین کنید چه نوع Stateهایی باید در برنامه قرار گیرند و هر قطعه State در کجا باید واقع شود.
قوانین کلی برای تعیین نوع دادههایی که باید در Redux قرار بگیرند کدامند؟
برخی از قوانین عمومی برای تعیین نوع دادههایی که باید در Redux قرار بگیرند، شامل موارد زیر است:
- آیا سایر بخشهای برنامه تمایل دارند دادههای مفروض را دریافت کنند؟
- آیا ضرورت دارد که بر اساس دادههای اصلی، دادههای مشتقشده بیشتری ایجاد شود؟
- آیا برای هدایت چندین کامپوننت از دادههای یکسانی استفاده میشود؟
- آیا اینکه بتوانید State را به یک نقطه زمانی معین بازگردانید برای شما مطلوب است؟ یعنی امکان اشکالزدایی در تاریخچه State برای شما جالب و مفید است؟
- آیا میخواهید دادهها را در حافظه Cache نگه دارید؟ یعنی به جای ارسال مجدد درخواست، از آنچه در State موجود است استفاده کنید؟
- آیا میخواهید زمان «بارگذاری مجدد بیدرنگ» (Hot Reload) کامپوننتهای رابط کاربری، دادهها حفظ شوند؟ (چراکه ممکن است هنگام سواپ، State داخلی خود را از دست بدهند.
تعدادی بستههای انجمنی نیز وجود دارند که به عنوان روش جایگزین، رویکردهای مختلفی را برای ذخیره State کامپوننت در Store اجرا میکند. از جمله میتوان به redux-component ، redux-react-local و سایر موارد اشاره کرد. همچنین میتوان اصول و مفهوم Reducerها را برای بهروزرسانی State کامپوننتهای محلی به موازات کد زیر به کار برد:
this.setState( (previousState) => reducer(previousState, someAction))
آیا باید از دستور switch برای مدیریت Actionها استفاده کنیم؟
خیر؛ شما میتوانید از هر رویکردی که میخواهید برای پاسخ به Action در Reducer استفاده کنید. دستورswitch رویکردی رایج است، اما استفاده از دستورif و یا جدول جستجوی تابعها نیز امکانپذیر است. علاوه بر آن میتوان تابعی توسعه داد که مدیریت Action را انتزاعی میکند. در واقع، در حالی که Redux مستلزم آن است که اشیاء Action حاوی یک فیلدtype باشند، اما منطق Reducer برای مدیریت Action نباید به آن وابستگی داشته باشد. همانطور که گفته شد، رویکرد استاندارد، استفاده از دستور سوئیچ یا یک جدول جستجو بر اساسtype است.
چگونه State را بین دو Reducer به اشتراک بگذاریم؟ آیا باید از combinationReducers استفاده کنیم؟
ساختار پیشنهادی برای یک Store اینطور است که شی State به چند «تکه» (Slice) یا «دامنه» (Domain) توسط کلید تقسیم شود و یک تابع Reducer جداگانه برای مدیریت هر تکه داده جداگانه ارائه شود. این ساختار همانند این است که الگوی استاندارد Flux چندین Store مستقل دارد و ریداکس تابع ابزاریcombinationReducers را برای آسانتر کردن این الگو فراهم میکند.
با این حال، توجه به این نکته مهم است کهcombinerReducers مورد نیاز نیست. combinerReducers صرفا یک تابع ابزاری برای داشتن یک تابع Reducer یکتا برای هر قطعه State، با اشیاء جاوا اسکریپت ساده برای دادهها است. بسیاری از کاربران میخواهند دادهها را بین دو Reducer بهاشتراک بگذارند، اما متوجه میشوند که combinerReducers به آنها این امکان را نمیدهد. چندین روش برای انجام این کار وجود دارد:
- اگر یک Reducer نیاز به دانستن دادهها از تکه State دیگری داشته باشد، شکل درخت State ممکن است نیاز به سازماندهی مجدد داشته باشد. بنابراین یک Reducer یکتا دادههای بیشتری را مدیریت میکند.
- برای مدیریت برخی از این Actionها ممکن است شما به نوشتن چند تابع سفارشی نیاز پیدا کنید و درنتیجه بخواهیدcombinerReducersرا با تابع Reducer خودتان جایگزین کنید. همچنین میتوانید از Utility مانند reducer-reducers برای اجرایcombinerReducersبرای مدیریت بیشتر Actionها استفاده کنید. همچنین میتوانید یک Reducer تخصصیتر را برای Actionهای خاص و فراتر از تکههای State اجرا کنید.
- «میانافزارهای» (Middleware) با منطق Async، مانند redux-thunk از طریقgetState() به کل Stateها دسترسی دارند. یک Action Creator میتواند دادههای اضافی را از State بازیابی کرده و در یک Action قرار دهد، به طوری که هر Reducer اطلاعات کافی را برای بهروزرسانی تکه State خود را داشته باشد.
جمعبندی
در این مقاله به معرفی کتابخانه Redux پرداختیم و در مورد اینکه ریداکس چیست بحث کردیم. در ادامه خلاصهای از مهمترین نکات اشاره شده در مقاله آمده است.
- ریداکس یک کتابخانه برای مدیریت State عمومی برنامه است.
- ریداکس معمولاً با کتابخانه React-Redux برای یکپارچهسازی Redux و React بهکار گرفته میشود.
- Redux Toolkit راه پیشنهادی برای نوشتن منطق ریداکس است.
- ریداکس از ساختار برنامه «جریان داده یکطرفه» استفاده میکند.
- State، وضعیت برنامه را در یک نقطه از زمان توصیف میکند و UI بر اساس آن State رندر میشود.
- وقتی رویدادی در برنامه اتفاق میافتد:
- UI یک Action را ارسال میکند.
- Store، کاهندهها را اجرا میکند و State بر اساس آنچه بهروز میشود که رخ داده است.
- Store تغییر State را به UI اطلاعرسانی میکند.
- UI بر اساس State جدید دوباره رندر میشود.
- ریداکس از چندین نوع کد استفاده میکند.
- Actionها اشیا ساده با فیلدtypeهستند و «آنچه اتفاق افتاده» را در برنامه توصیف میکنند.
- Reducerها تابعهایی هستند که مقدار State جدید را بر اساس State قبلی و با در نظر گرفتن Action محاسبه میکنند.
- Store، هر زمان که یک Action ارسال شود، Reducer ریشه را اجرا میکند.