جریان داده در Redux توضیح داده شده – راهنمای مدیریت دولتی
در برنامه های پیچیده React، مدیریت وضعیت برنامه به طور موثر می تواند به یک چالش تبدیل شود. اینجا جایی است که Redux، یک کتابخانه مدیریت دولتی قابل پیش بینی، وارد عمل می شود.
Redux با معرفی یک جریان داده یک طرفه، نظم و وضوح را در نحوه به روز رسانی داده ها و تعامل در اجزای React شما به ارمغان می آورد.
این مقاله به تحلیل عملکرد درونی Redux می پردازد، به طور خاص بر نحوه جریان داده ها در برنامه شما تمرکز می کند. ما مفاهیم اصلی مانند فروشگاه Redux، اقدامات، کاهندهها و انتخابکنندهها را به همراه مثالهای عملی از نحوه کار آنها برای مدیریت یکپارچه وضعیت برنامه شما با هم تحلیل خواهیم کرد.
فهرست مطالب
چرا از Redux برای مدیریت داده استفاده کنیم؟
مفاهیم اصلی جریان داده Redux
* جریان داده های یک طرفه
* مزایای جریان داده های یک طرفه
مدیریت دولتی با فروشگاه Redux
* فروشگاه Redux چیست؟
* ساختار فروشگاه (ایالت، کاهش دهنده ها، اقدامات)
اقدامات: آغاز تغییرات حالت
* Action Creators (توابع برای ایجاد اقدامات)
* انواع اقدام (تشخیص اقدامات مختلف)
نحوه پردازش تغییرات حالت
* توابع خالص: کاهش دهنده ها در هسته
* ویژگی های توابع خالص
آناتومی یک عملکرد کاهنده
* پارامترها: حالت قبلی و هدف اقدام
* ارزش بازگشتی: وضعیت به روز شده
نحوه انجام اقدامات مختلف در کاهش دهنده ها
* استفاده از دستورات سوئیچ یا منطق شرطی
اقدامات ارسال: نحوه به روز رسانی فروشگاه Redux
* تابع dispatch
* ارسال اقدامات از اجزا یا رویدادها
نحوه دسترسی به داده های خاص از فروشگاه
* ایجاد توابع انتخابگر
* ذخیره سازی برای استفاده از انتخابگر کارآمد
نحوه اتصال React Components به Redux
* تابع connect
از کتابخانه react-redux
* وضعیت نقشه برداری و ارسال به Props
* استفاده از اجزای متصل در برنامه شما
تکنیک های پیشرفته جریان داده Redux
* اقدامات ناهمزمان (Redux Thunk، Redux Saga)
* میان افزار برای گسترش عملکرد Redux
Redux چیست؟
Redux یک محفظه حالت قابل پیش بینی برای برنامه های جاوا اسکریپت است که در درجه اول با کتابخانه هایی مانند React استفاده می شود. این به مدیریت وضعیت برنامه در یک فروشگاه متمرکز کمک می کند و مدیریت و به روز رسانی وضعیت را در کل برنامه شما آسان تر می کند.
به زبان ساده، Redux راهی برای ذخیره و مدیریت داده هایی که برنامه شما برای کار به آن نیاز دارد، ارائه می دهد. از یک الگوی دقیق پیروی می کند تا اطمینان حاصل شود که تغییرات حالت قابل پیش بینی و مدیریت هستند.
چرا از Redux برای مدیریت داده استفاده کنیم؟
استفاده از Redux برای مدیریت داده در برنامه شما چندین مزیت دارد:
مدیریت حالت متمرکز : Redux وضعیت برنامه را در یک فروشگاه ذخیره می کند و مدیریت و اشکال زدایی آن را در مقایسه با حالت پراکنده در چندین مؤلفه آسان تر می کند.
تغییرات حالت قابل پیش بینی : جهش های حالت از طریق کاهنده ها انجام می شود که توابع خالص هستند. این تضمین میکند که تغییرات حالت قابل پیشبینی و ردیابی هستند و درک نحوه جریان دادهها در برنامه شما را آسانتر میکند.
اشکال زدایی آسانتر : با یک منبع حقیقت واحد، اشکال زدایی ساده تر می شود. میتوانید تغییرات وضعیت را ثبت کنید، اقدامات را دنبال کنید، و حتی اشکالزدایی سفر در زمان (از طریق Redux DevTools) را برای پخش مجدد اقدامات و بازرسی وضعیت در هر نقطه از زمان اجرا کنید.
تست را تسهیل می کند : از آنجایی که کاهنده ها توابع خالصی هستند که فقط به ورودی آنها بستگی دارند و خروجی قابل پیش بینی تولید می کنند، آزمایش ساده می شود. شما به راحتی می توانید آزمایش کنید که چگونه کاهنده ها وضعیت را در پاسخ به اقدامات مختلف به روز می کنند.
جریان داده های یک جهته را اعمال می کند : Redux از یک الگوی دقیق جریان داده یک جهته پیروی می کند. دادهها در یک جهت جریان مییابند: اقدامات ارسال میشوند، کاهشدهندهها وضعیت را بهطور تغییرناپذیر بهروزرسانی میکنند، و مؤلفهها مشترک تغییراتی هستند که به آنها علاقهمند هستند. این الگو مدیریت دادهها را ساده میکند و باگهای مربوط به وضعیت ناسازگار را کاهش میدهد.
تداوم حالت را تسهیل می کند : Redux تداوم وضعیت برنامه شما را در جلسات یا ذخیره آن به صورت محلی آسان تر می کند و با حفظ داده ها بین بازدیدها، تجربه کاربر را بهبود می بخشد.
مقیاس پذیری : Redux به دلیل مدیریت متمرکز حالت آن، به خوبی با برنامه های کاربردی بزرگ مقیاس می شود. همانطور که برنامه شما رشد می کند، مدیریت حالت در مقایسه با استفاده از حالت مولفه محلی یا حفاری پایه، قابل مدیریت تر و کمتر مستعد خطا می شود.
مفاهیم اصلی جریان داده Redux
درک مفاهیم اصلی جریان داده Redux برای تسلط بر مدیریت حالت در برنامه های جاوا اسکریپت مدرن ضروری است.
جریان داده یک طرفه
Redux از یک الگوی دقیق جریان داده یک طرفه پیروی می کند، به این معنی که داده ها در برنامه شما در یک جهت از طریق یک سری مراحل حرکت می کنند:
Actions : Actions اشیاء ساده جاوا اسکریپت هستند که نشان دهنده قصد تغییر وضعیت هستند. آنها تنها منبع اطلاعات فروشگاه هستند.
کاهنده ها : کاهنده ها توابع خالصی هستند که مسئولیت مدیریت انتقال حالت بر اساس کنش ها را بر عهده دارند. آنها مشخص می کنند که چگونه وضعیت برنامه در پاسخ به اقدامات ارسال شده به فروشگاه تغییر می کند.
Store : فروشگاه وضعیت برنامه را نگه می دارد. این امکان دسترسی به ایالت را از طریق getState()
فراهم می کند، وضعیت را از طریق dispatch(action)
به روز می کند و شنوندگان را از طریق subscribe(listener)
ثبت می کند.
مشاهده : اجزای React (یا هر لایه رابط کاربری دیگری) در فروشگاه مشترک می شوند تا در صورت تغییر وضعیت، به روز رسانی ها را دریافت کنند. سپس بر اساس وضعیت به روز شده، دوباره رندر می شوند.
در اینجا یک نمای کلی ساده از نحوه عملکرد جریان داده های یک طرفه در Redux آورده شده است:
Action Dispatch : اجزاء با استفاده از store.dispatch(action)
اقدامات را به فروشگاه Redux ارسال می کنند. Action ها اشیاء جاوا اسکریپت ساده با یک فیلد type
هستند که نوع عمل انجام شده را توصیف می کند.
Action Handling : فروشگاه عملیات ارسال شده را به روت کاهنده ارسال می کند. کاهنده یک تابع خالص است که وضعیت فعلی و عمل را می گیرد، وضعیت جدید را بر اساس عمل محاسبه می کند و وضعیت به روز شده را برمی گرداند.
به روز رسانی وضعیت : فروشگاه Redux وضعیت خود را بر اساس مقدار بازگشتی کاهش دهنده ریشه به روز می کند. همه اجزای مشترک شده را از تغییر وضعیت مطلع می کند.
رندر مجدد مؤلفه : مؤلفههایی که در فروشگاه مشترک شدهاند، وضعیت بهروزشده را بهعنوان پایه دریافت میکنند. آنها با داده های جدید دوباره رندر می شوند.
مزایای جریان داده های یک طرفه
پیش بینی پذیری : Redux با اعمال یک جهت واحد برای جریان داده، تغییرات حالت را قابل پیش بینی تر و قابل درک تر می کند. کنشها در مورد تغییراتی که در حال رخ دادن هستند صریح هستند و کاهشدهندهها به وضوح نحوهی وقوع انتقال حالت را مشخص میکنند.
اشکال زدایی : جریان داده های یک طرفه اشکال زدایی را ساده می کند زیرا می توانید نحوه انتشار تغییرات حالت را در برنامه خود ردیابی کنید. Redux DevTools با اجازه دادن به شما برای ردیابی اقدامات، بازرسی تغییرات وضعیت در طول زمان، و حتی بازپخش اقدامات برای بازتولید اشکالات، این را بیشتر تقویت می کند.
قابلیت نگهداری : Redux با تفکیک واضح بین داده ها (وضعیت) و منطق (کاهش دهنده ها)، کد پاک تر و قابل نگهداری تر را ترویج می کند. احتمال بروز اشکالات ناشی از جهش های حالت ناسازگار یا عوارض جانبی را کاهش می دهد.
مقیاس پذیری : با افزایش اندازه و پیچیدگی برنامه شما، جریان داده های یک طرفه به مدیریت موثرتر به روز رسانی های حالت کمک می کند. از مشکلات اتصال دو طرفه داده ها جلوگیری می کند و تضمین می کند که تغییرات در حالت کنترل شده و قابل مدیریت هستند.
آزمایش : از آنجایی که کاهنده ها توابع خالصی هستند که ورودی ها را دریافت می کنند و خروجی ها را بدون عوارض جانبی تولید می کنند، آزمایش واحد ساده می شود. میتوانید کاهشدهندهها را با کنشها و سناریوهای مختلف آزمایش کنید تا مطمئن شوید که مطابق انتظار رفتار میکنند.
مدیریت دولتی با فروشگاه Redux
مدیریت ایالت نقشی اساسی در توسعه وب مدرن ایفا میکند و تضمین میکند که برنامهها حالتهای سازگار و قابل پیشبینی را در اجزای مختلف حفظ میکنند.
فروشگاه Redux چیست؟
فروشگاه Redux قلب مدیریت دولتی Redux است. کل درخت حالت برنامه شما را نگه می دارد. فروشگاه به شما اجازه می دهد:
از طریق store.getState()
به وضعیت فعلی برنامه خود دسترسی پیدا کنید.
اعمال را برای تغییر وضعیت با استفاده از store.dispatch(action)
ارسال کنید.
در تغییرات وضعیت مشترک شوید تا اجزای شما بتوانند بر اساس آن با استفاده از store.subscribe(listener)
به روز شوند.
در اصل، Redux Store به عنوان یک مخزن متمرکز برای وضعیت برنامه شما عمل می کند، جریان داده قابل پیش بینی را تسهیل می کند و مدیریت وضعیت را قابل مدیریت تر می کند.
ساختار فروشگاه (State، Reducers، Actions)
وضعیت موجود در Redux نشان دهنده کل وضعیت برنامه شما است. به طور معمول به عنوان یک شی جاوا اسکریپت ساده ساختار یافته است. شکل حالت توسط کاهنده ها تعریف می شود. مثلا:
const initialState = { todos: [], visibilityFilter: 'SHOW_ALL', };
در این مثال، todos
و visibilityFilter
بخشهایی از حالت هستند که توسط Redux مدیریت میشوند.
کاهش دهنده ها توابعی هستند که نحوه تغییر وضعیت برنامه را در پاسخ به اقدامات ارسال شده به فروشگاه مشخص می کنند. آنها وضعیت فعلی و یک عمل را به عنوان آرگومان در نظر می گیرند و بر اساس نوع عمل وضعیت جدید را برمی گردانند.
کاهنده ها باید توابع خالص باشند، به این معنی که خروجی یکسانی را برای ورودی یکسان تولید می کنند و حالت را مستقیماً تغییر نمی دهند.
const todosReducer = (state = [], action) => { switch (action.type) { case 'ADD_TODO': return [ ...state, { id: action.id, text: action.text, completed: false } ]; case 'TOGGLE_TODO': return state.map(todo => (todo.id === action.id) ? { ...todo, completed: !todo.completed } : todo ); default: return state; } };
در این مثال، todosReducer
وضعیت todos
را مدیریت میکند و اقداماتی مانند 'ADD_TODO'
و 'TOGGLE_TODO'
برای اضافه کردن کارهای جدید یا تغییر وضعیت تکمیل آنها مدیریت میکند.
Action ها اشیاء ساده جاوا اسکریپت هستند که آنچه را که در برنامه شما اتفاق افتاده است را توصیف می کنند. آنها تنها منبع اطلاعات فروشگاه هستند. کنشها معمولاً دارای یک فیلد type
هستند که نوع عمل انجام شده را نشان میدهد، و همچنین ممکن است دادههای اضافی لازم برای عمل را حمل کنند.
const addTodo = (text) => ({ type: 'ADD_TODO', id: nextTodoId++, text }); const toggleTodo = (id) => ({ type: 'TOGGLE_TODO', id });
در این مثال، addTodo
و toggleTodo
توابع ایجاد کنش هستند که به ترتیب اقداماتی را برای گفت ن یک کار جدید و تغییر وضعیت تکمیل یک کار انجام می دهند.
رابطه بین این عناصر در Redux برای مدیریت موثر وضعیت برنامه بسیار مهم است:
کنشها رویدادهایی را که در برنامه شما رخ میدهند توصیف میکنند.
کاهش دهنده ها مشخص می کنند که چگونه وضعیت برنامه در پاسخ به اقدامات تغییر می کند.
Store وضعیت برنامه را نگه می دارد و به شما امکان می دهد اقداماتی را برای به روز رسانی وضعیت ارسال کنید.
این مؤلفه ها با هم ساختار اصلی مدیریت حالت Redux را تشکیل می دهند و راهی واضح و قابل پیش بینی برای مدیریت و به روز رسانی وضعیت برنامه در کل برنامه شما ارائه می دهند.
اقدامات: آغاز تغییرات حالت
مدیریت وضعیت به طور موثر در هسته ایجاد برنامه های کاربردی پویا و پاسخگو قرار دارد. اقدامات، در معماری Redux و کتابخانه های مدیریت دولتی مشابه، به عنوان عناصر مهم برای شروع تغییرات حالت عمل می کنند.
Action Creators (توابع برای ایجاد کنشها)
Action creators در Redux توابعی هستند که اشیاء اکشن را ایجاد و برمی گرداند. این اشیاء عملیاتی آنچه را که در برنامه شما اتفاق افتاده است توصیف میکنند و به فروشگاه Redux ارسال میشوند تا تغییرات حالت را آغاز کنند.
سازندگان اکشن منطق ایجاد اکشنها را محصور میکنند و کد شما را ماژولارتر میکنند و آزمایش آن را آسانتر میکنند.
در اینجا یک نمونه از یک اکشن خالق آورده شده است:
// Action creator function const addTodo = (text) => ({ type: 'ADD_TODO', id: nextTodoId++, text }); // Usage of the action creator const newTodoAction = addTodo('Buy groceries');
در این مثال:
addTodo
یک تابع ایجاد کننده اکشن است که text
به عنوان پارامتر می گیرد و یک شی اکشن را برمی گرداند.
شی اکشن دارای یک فیلد type
( 'ADD_TODO'
) است که نوع عمل و فیلدهای اضافی ( id
و text
) را که داده های لازم را برای عمل ارائه می دهند، مشخص می کند.
سازندگان اکشن فرآیند ایجاد کنشها را ساده میکنند، بهویژه زمانی که کنشها قبل از ارسال به دادهها یا محاسبات پیچیده نیاز دارند.
انواع اقدام (تشخیص اقدامات مختلف)
انواع عمل در Redux ثابت های رشته ای هستند که نوع عمل انجام شده را مشخص می کنند. آنها برای شناسایی و تمایز اقدامات مختلفی که می توانند به فروشگاه Redux ارسال شوند استفاده می شوند. Redux با استفاده از ثابتهای رشتهای برای انواع کنش، تضمین میکند که انواع کنشها منحصربهفرد هستند و به راحتی میتوان آنها را در سرتاسر برنامهتان ارجاع داد.
در اینجا نحوه تعریف انواع عمل به طور معمول آمده است:
// Action types as constants const ADD_TODO = 'ADD_TODO'; const TOGGLE_TODO = 'TOGGLE_TODO'; const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER';
این ثابتها ( ADD_TODO
، TOGGLE_TODO
، SET_VISIBILITY_FILTER
) اقدامات مختلفی را نشان میدهند که میتوانند در برنامه شما رخ دهند، مانند گفت ن یک todo، تغییر وضعیت تکمیل یک todo، یا تنظیم یک فیلتر دید برای کارها.
نوع عمل معمولاً در اشیاء اکشن ایجاد شده توسط سازندگان اکشن استفاده میشود و در کاهشدهندهها با هم تطبیق داده میشوند تا مشخص شود وضعیت چگونه باید در پاسخ به هر عمل تغییر کند.
// Example of using action types in a reducer const todosReducer = (state = [], action) => { switch (action.type) { case ADD_TODO: return [ ...state, { id: action.id, text: action.text, completed: false } ]; case TOGGLE_TODO: return state.map(todo => (todo.id === action.id) ? { ...todo, completed: !todo.completed } : todo ); default: return state; } };
در این مثال:
ADD_TODO
و TOGGLE_TODO
انواع کنشهایی هستند که در todosReducer
برای مدیریت انواع مختلف کنشها استفاده میشوند ( 'ADD_TODO'
و 'TOGGLE_TODO'
).
فیلد action.type
در دستور switch تضمین می کند که کاهنده به هر اقدام ارسال شده بر اساس نوع آن پاسخ مناسب می دهد.
نحوه پردازش تغییرات حالت
در قلب مدیریت دولتی، کاهندهها، توابع خالص طراحی شدهاند تا انتقال حالت را به شیوهای کنترلشده و تغییرناپذیر مدیریت کنند.
توابع خالص: کاهش دهنده ها در هسته
کاهش دهنده ها در Redux توابع خالصی هستند که مسئول تعیین نحوه تغییر وضعیت برنامه در پاسخ به اقدامات ارسال شده به فروشگاه هستند. آنها حالت فعلی و یک عمل را به عنوان آرگومان در نظر می گیرند و بر اساس نوع عمل وضعیت جدید را برمی گردانند.
در اینجا خلاصه ای از نحوه کار کاهنده ها و نقش آنها در مدیریت تغییرات حالت آورده شده است:
توابع خالص : کاهنده ها توابع خالص هستند، به این معنی که آنها:
هر بار که آنها فراخوانی می شوند، خروجی یکسانی را برای ورودی یکسان تولید کنید.
هیچ گونه عارضه جانبی (مانند اصلاح آرگومان ها یا متغیرهای جهانی) ایجاد نکنید.
حالت را مستقیماً تغییر ندهید، بلکه در عوض یک شیء جدید را برگردانید.
Handling State Transitions : Reducer ها مشخص می کنند که چگونه وضعیت برنامه در پاسخ به انواع مختلف اقدامات تغییر می کند. آنها از وضعیت فعلی و عملکرد ارسال شده برای محاسبه و برگرداندن وضعیت جدید استفاده می کنند.
// Example of a todos reducer const todosReducer = (state = [], action) => { switch (action.type) { case 'ADD_TODO': return [ ...state, { id: action.id, text: action.text, completed: false } ]; case 'TOGGLE_TODO': return state.map(todo => (todo.id === action.id) ? { ...todo, completed: !todo.completed } : todo ); default: return state; } };
در این مثال:
todosReducer
یک تابع خالص است که state
(آرایه todos فعلی) و action
به عنوان آرگومان می گیرد.
بسته به action.type
، حالت جدیدی را محاسبه کرده و برمی گرداند (آرایه todos به روز شده).
بهروزرسانیهای وضعیت غیرقابل تغییر : کاهندهها هرگز نباید مستقیماً حالت را تغییر دهند. در عوض، آنها کپی هایی از حالت ایجاد می کنند و کپی ها را برای تولید یک شیء جدید تغییر می دهند. این تضمین می کند که Redux می تواند تغییرات حالت را تشخیص دهد و مؤلفه ها را به طور موثر به روز کند.
اصل مسئولیت منفرد : هر کاهنده معمولاً بهروزرسانیهای یک بخش خاص از وضعیت برنامه را مدیریت میکند. این به حفظ تفکیک واضح نگرانیها کمک میکند و درک، آزمایش و نگهداری کاهندهها را آسانتر میکند.
ویژگی های توابع خالص
توابع خالص، از جمله کاهش دهنده های Redux، دارای ویژگی های خاصی هستند که آنها را برای مدیریت تغییرات حالت مناسب می کند:
قطعی : یک تابع خالص همیشه خروجی یکسانی را برای ورودی یکسان تولید می کند. این پیشبینیپذیری تضمین میکند که کاهندهها بهطور مداوم رفتار میکنند و استدلال کردن در مورد آن آسانتر است.
بدون عوارض جانبی : توابع خالص آرگومان های ورودی یا هیچ حالت خارجی را تغییر نمی دهند. آنها فقط به پارامترهای ورودی خود بستگی دارند و بدون ایجاد عوارض جانبی قابل مشاهده، خروجی تولید می کنند.
داده های تغییرناپذیر : توابع خالص داده ها را تغییر نمی دهند. در عوض، آنها ساختارهای داده جدیدی را ایجاد و برمی گرداند. در Redux، کاهندهها یک شیء حالت جدید را بدون تغییر وضعیت موجود تولید میکنند و امکان تشخیص کارآمد تغییرات و مدیریت وضعیت را فراهم میکنند.
شفافیت مرجع : توابع خالص را می توان با مقادیر بازگشتی خود جایگزین کرد بدون اینکه بر صحت برنامه تأثیر بگذارد. این ویژگی از ترکیب پذیری پشتیبانی می کند و آزمایش و استدلال در مورد کد را آسان تر می کند.
آناتومی یک عملکرد کاهنده
یک تابع کاهنده، در هسته خود، نحوه تغییر وضعیت برنامه در پاسخ به اقدامات ارسال شده را تعریف می کند. این تابع دو پارامتر را دریافت می کند: وضعیت فعلی و یک شی اکشن که وضعیت جدید را بر اساس نوع عملکرد دریافت شده تعیین می کند.
پارامترها: حالت قبلی و هدف اقدام
یک تابع کاهنده در Redux یک تابع خالص است که دو پارامتر دارد: حالت قبلی (وضعیت قبل از اعمال عمل) و یک شی اکشن. این پارامترها نحوه محاسبه حالت بعدی برنامه را توسط کاهنده تعیین می کنند.
حالت قبلی : این پارامتر نشان دهنده وضعیت فعلی برنامه قبل از ارسال عمل است. تغییرناپذیر است و نباید مستقیماً در کاهنده اصلاح شود.
Action Object : یک Action Object یک شیء ساده جاوا اسکریپت است که آنچه را که در برنامه شما اتفاق افتاده است را توصیف می کند. معمولاً دارای یک فیلد type
است که نوع عمل انجام شده را نشان می دهد. سایر فیلدها در شی اقدام ممکن است داده های اضافی لازم برای به روز رسانی حالت را ارائه دهند.
const action = { type: 'ADD_TODO', id: 1, text: 'Buy groceries' };
در این مثال، action.type
'ADD_TODO'
است، که نشان میدهد ما میخواهیم یک مورد جدید todo را به حالت اضافه کنیم.
مقدار بازگشتی: وضعیت به روز شده
تابع کاهنده باید وضعیت به روز شده را بر اساس وضعیت قبلی و شیء عمل به آن ارسال کند. حالت به روز شده معمولاً یک شی جدید است که وضعیت برنامه را پس از اعمال عمل نشان می دهد.
در اینجا ساختار اصلی یک تابع کاهنده آورده شده است:
const initialState = { todos: [], visibilityFilter: 'SHOW_ALL' }; const todoAppReducer = (state = initialState, action) => { switch (action.type) { case 'ADD_TODO': return { ...state, todos: [ ...state.todos, { id: action.id, text: action.text, completed: false } ] }; case 'TOGGLE_TODO': return { ...state, todos: state.todos.map(todo => (todo.id === action.id) ? { ...todo, completed: !todo.completed } : todo ) }; case 'SET_VISIBILITY_FILTER': return { ...state, visibilityFilter: action.filter }; default: return state; } };
در این مثال:
todoAppReducer
یک تابع کاهش دهنده است که وضعیت todos و فیلترهای دید را مدیریت می کند.
state
(وضعیت قبلی) و action
به عنوان پارامتر می گیرد.
بسته به action.type
، یک شیء حالت جدید را محاسبه و برمی گرداند که تغییرات ناشی از عمل را منعکس می کند.
امتیاز کلیدی:
بهروزرسانی غیرقابل تغییر : کاهندهها هرگز نباید مستقیماً وضعیت قبلی را تغییر دهند. در عوض، با کپی کردن حالت قبلی ( ...state
) و اعمال تغییرات در آن، یک شیء جدید ایجاد می کنند.
حالت پیشفرض : اگر کاهنده نوع عمل را تشخیص ندهد، حالت default
در دستور switch
وضعیت فعلی را بدون تغییر برمیگرداند. این تضمین می کند که کاهنده همیشه یک شیء حالت معتبر را برمی گرداند، حتی اگر هیچ تغییری ایجاد نشود.
مسئولیت منفرد : هر مورد در دستور switch
مربوط به یک نوع عمل خاص است و مسئول به روز رسانی یک بخش خاص از وضعیت برنامه است. این امر به تفکیک واضح نگرانیها کمک میکند و درک و نگهداری کاهندهها را آسانتر میکند.
نحوه انجام اقدامات مختلف در کاهش دهنده ها
در Redux، می توانید با استفاده از دستورهای سوئیچ یا منطق شرطی، اقدامات مختلفی را در کاهش دهنده ها انجام دهید. هدف هر دو رویکرد تعیین چگونگی تغییر وضعیت برنامه بر اساس نوع اقدام ارسال شده است.
استفاده از دستورات سوئیچ
عبارات سوئیچ معمولاً در کاهش دهنده های Redux برای مدیریت انواع عملکردهای مختلف استفاده می شوند. هر case
در دستور switch مربوط به یک نوع عمل خاص است و کاهش دهنده منطق مربوطه را بر اساس نوع عمل اجرا می کند.
در اینجا مثالی از استفاده از دستورات سوئیچ در یک کاهنده آورده شده است:
const initialState = { todos: [], visibilityFilter: 'SHOW_ALL' }; const todoAppReducer = (state = initialState, action) => { switch (action.type) { case 'ADD_TODO': return { ...state, todos: [ ...state.todos, { id: action.id, text: action.text, completed: false } ] }; case 'TOGGLE_TODO': return { ...state, todos: state.todos.map(todo => (todo.id === action.id) ? { ...todo, completed: !todo.completed } : todo ) }; case 'SET_VISIBILITY_FILTER': return { ...state, visibilityFilter: action.filter }; default: return state; } };
در این مثال:
تابع todoAppReducer
از یک دستور سوئیچ برای مدیریت انواع عملکردهای مختلف استفاده می کند ( 'ADD_TODO'
، 'TOGGLE_TODO'
، 'SET_VISIBILITY_FILTER'
).
هر بلوک case
مشخص می کند که چگونه وضعیت باید در پاسخ به نوع اقدام مربوطه به روز شود.
اگر کاهنده نوع عمل را تشخیص ندهد، حالت default
حالت فعلی را بدون تغییر برمیگرداند و تضمین میکند که کاهنده همیشه یک شیء حالت معتبر را برمیگرداند.
استفاده از منطق شرطی
از طرف دیگر، کاهنده ها همچنین می توانند از منطق شرطی (عبارات if-else) برای تعیین نحوه به روز رسانی حالت بر اساس نوع عمل استفاده کنند. در حالی که کمتر از عبارات سوئیچ در Redux رایج است، منطق شرطی می تواند به طور مشابه برای مدیریت اقدامات استفاده شود.
در اینجا مثالی از استفاده از منطق شرطی در یک کاهنده آورده شده است:
const todoAppReducer = (state = initialState, action) => { if (action.type === 'ADD_TODO') { return { ...state, todos: [ ...state.todos, { id: action.id, text: action.text, completed: false } ] }; } else if (action.type === 'TOGGLE_TODO') { return { ...state, todos: state.todos.map(todo => (todo.id === action.id) ? { ...todo, completed: !todo.completed } : todo ) }; } else if (action.type === 'SET_VISIBILITY_FILTER') { return { ...state, visibilityFilter: action.filter }; } else { return state; } };
در این مثال:
تابع todoAppReducer
از دستورهای if-else برای تحلیل نوع عمل ( action.type
) و اجرای منطق متفاوت بر اساس نوع عمل استفاده می کند.
هر شرط مشخص می کند که چگونه وضعیت باید برای نوع اقدام مربوطه به روز شود.
اگر نوع عمل شناسایی نشود، بلوک else
نهایی، وضعیت فعلی را بدون تغییر برمیگرداند.
انتخاب بین دستورات سوئیچ و منطق شرطی
1. تغییر بیانیه ها:
مزایا: عبارات سوئیچ معمولاً هنگام مدیریت چندین نوع عملکرد در کاهش دهنده های Redux قابل خواندن و نگهداری هستند. آنها به وضوح موارد مختلف را بر اساس انواع عمل جدا می کنند.
ملاحظات: اطمینان حاصل کنید که هر نوع اقدام دارای یک case
متناظر در عبارت switch است تا بهروزرسانیها را به درستی مدیریت کند.
2. منطق شرطی:
مزایا: منطق شرطی (گزارههای if-else) انعطافپذیری را فراهم میکند و در سناریوهای خاصی که انواع اقدامات کمتری وجود دارد، میتوان آن را آسانتر درک کرد.
ملاحظات: در رسیدگی به انواع کنشها سازگاری داشته باشید و اطمینان حاصل کنید که هر شرط بهروزرسانیهای حالت را به درستی مدیریت میکند.
در عمل، عبارات سوئیچ به دلیل وضوح و قراردادی که در جامعه Redux دارند، رویکرد توصیه شده در کاهش دهنده های Redux هستند. آنها به حفظ یک رویکرد ساختاریافته برای مدیریت تغییرات حالت بر اساس انواع عملکردهای مختلف کمک میکنند و ثبات و پیشبینیپذیری را در برنامههای Redux ارتقا میدهند.
اقدامات ارسال: نحوه به روز رسانی فروشگاه Redux
ارسال اقدامات در Redux برای مدیریت بهروزرسانیهای حالت در برنامه شما ضروری است. Redux، یک محفظه حالت قابل پیشبینی برای برنامههای جاوا اسکریپت، متکی به اقداماتی به عنوان محمولههای اطلاعاتی است که دادهها را از برنامه شما به فروشگاه Redux ارسال میکند.
تابع dispatch
در Redux، تابع dispatch
روشی است که توسط فروشگاه Redux ارائه شده است. از آن برای ارسال اقدامات برای ایجاد تغییرات حالت در برنامه استفاده می شود. هنگامی که یک اقدام ارسال می شود، فروشگاه Redux تابع کاهش دهنده مرتبط با آن را فراخوانی می کند، وضعیت جدید را محاسبه می کند و به همه مشترکین اطلاع می دهد که وضعیت به روز شده است.
در اینجا نحوه استفاده از تابع dispatch
آمده است:
import { createStore } from 'redux'; // Reducer function const counterReducer = (state = { count: 0 }, action) => { switch (action.type) { case 'INCREMENT': return { ...state, count: state.count + 1 }; case 'DECREMENT': return { ...state, count: state.count - 1 }; default: return state; } }; // Create Redux store const store = createStore(counterReducer); // Dispatch actions to update state store.dispatch({ type: 'INCREMENT' }); store.dispatch({ type: 'DECREMENT' });
در این مثال:
ما یک فروشگاه Redux با استفاده از createStore
ایجاد می کنیم و تابع counterReducer
را عبور می دهیم.
تابع store.dispatch
برای ارسال کنشها ( { type: 'INCREMENT' }
and { type: 'DECREMENT' }
) برای بهروزرسانی وضعیت استفاده میشود.
هر اقدام ارسال شده، مورد مربوطه را در کاهنده ایجاد می کند و وضعیت را همانطور که تعریف شده به روز می کند.
ارسال اقدامات از اجزا یا رویدادها
در یک برنامه معمولی Redux، اقدامات اغلب از اجزای React در پاسخ به تعاملات کاربر یا رویدادهای دیگر ارسال میشوند.
برای ارسال کنشها از مؤلفهها، معمولاً مؤلفه را با استفاده از تابع connect
React Redux یا قلابهایی مانند useDispatch
به فروشگاه Redux متصل میکنید.
در اینجا نحوه ارسال اقدامات از یک مؤلفه React با استفاده از connect
و mapDispatchToProps
آورده شده است:
import React from 'react'; import { connect } from 'react-redux'; // Action creator functions const increment = () => ({ type: 'INCREMENT' }); const decrement = () => ({ type: 'DECREMENT' }); // Component definition const Counter = ({ count, increment, decrement }) => ( <div> <p>Count: {count}</p> <button onClick={increment}>Increment</button> <button onClick={decrement}>Decrement</button> </div> ); // Map state to props const mapStateToProps = (state) => ({ count: state.count }); // Map dispatch to props const mapDispatchToProps = { increment, decrement }; // Connect component to Redux store export default connect(mapStateToProps, mapDispatchToProps)(Counter);
در این مثال:
increment
و decrement
توابع ایجاد کنش هستند که کنشها را برمیگردانند ( { type: 'INCREMENT' }
and { type: 'DECREMENT' }
).
جزء Counter
با استفاده از connect
به فروشگاه Redux متصل می شود. این count
از حالت Redux به عنوان یک پایه، همراه با سازندگان اکشن increment
و decrement
دریافت می کند.
با کلیک بر روی دکمه های "افزایش" و "کاهش" اقداماتی ارسال می شود که توسط کاهنده برای به روز رسانی حالت Redux انجام می شود.
از طرف دیگر، میتوانید از قلابهای React Redux ( useDispatch
) برای ارسال اقدامات در اجزای عملکردی استفاده کنید:
import React from 'react'; import { useDispatch, useSelector } from 'react-redux'; const Counter = () => { const count = useSelector(state => state.count); const dispatch = useDispatch(); const handleIncrement = () => { dispatch({ type: 'INCREMENT' }); }; const handleDecrement = () => { dispatch({ type: 'DECREMENT' }); }; return ( <div> <p>Count: {count}</p> <button onClick={handleIncrement}>Increment</button> <button onClick={handleDecrement}>Decrement</button> </div> ); }; export default Counter;
در این مثال جزء عملکردی:
useSelector
برای انتخاب count
از حالت ذخیره Redux استفاده می شود.
useDispatch
برای دریافت تابع dispatch
از فروشگاه Redux استفاده می شود.
handleIncrement
و handleDecrement
عملکردها را ارسال می کنند ( { type: 'INCREMENT' }
and { type: 'DECREMENT' }
) برای به روز رسانی حالت Redux هنگامی که دکمه ها کلیک می شوند.
نحوه دسترسی به داده های خاص از فروشگاه
دسترسی به داده های خاص از فروشگاه در Redux شامل پیمایش در ساختار حالت برنامه برای بازیابی اطلاعات دقیق مورد نیاز برای رندر کردن اجزا یا اجرای منطق است.
ایجاد توابع انتخابگر
انتخابگرها در Redux توابعی هستند که منطق بازیابی قطعات خاصی از داده از حالت ذخیره Redux را در بر می گیرند. آنها به جدا کردن اجزا از ساختار دولت کمک می کنند و دسترسی کارآمد به داده ها و تبدیل را تسهیل می کنند.
در اینجا نحوه ایجاد توابع انتخابگر آورده شده است:
// Example Redux state const initialState = { todos: [ { id: 1, text: 'Learn Redux', completed: false }, { id: 2, text: 'Write Redux selectors', completed: true }, // more todos... ], visibilityFilter: 'SHOW_COMPLETED' }; // Selector function to get todos from state const getTodos = (state) => state.todos; // Selector function to filter todos based on visibility filter const getVisibleTodos = (state) => { const todos = getTodos(state); const visibilityFilter = state.visibilityFilter; switch (visibilityFilter) { case 'SHOW_COMPLETED': return todos.filter(todo => todo.completed); case 'SHOW_ACTIVE': return todos.filter(todo => !todo.completed); case 'SHOW_ALL': default: return todos; } };
در این مثال:
getTodos
یک تابع انتخابگر است که آرایه todos
را از حالت Redux بازیابی می کند.
getVisibleTodos
یک تابع انتخابگر است که todos
بر اساس visibilityFilter
ذخیره شده در حالت فیلتر می کند.
انتخابگرها همچنین می توانند برای ایجاد انتخابگرهای پیچیده تر ترکیب شوند:
// Composed selector function to get visible todos const getVisibleTodos = (state) => { const todos = getTodos(state); const visibilityFilter = state.visibilityFilter; switch (visibilityFilter) { case 'SHOW_COMPLETED': return getCompletedTodos(todos); case 'SHOW_ACTIVE': return getActiveTodos(todos); case 'SHOW_ALL': default: return todos; } }; // Helper functions for filtering todos const getCompletedTodos = (todos) => todos.filter(todo => todo.completed); const getActiveTodos = (todos) => todos.filter(todo => !todo.completed);
ذخیره سازی برای استفاده از انتخابگر کارآمد
حافظهسازی تکنیکی است که برای بهینهسازی محاسبات گران قیمت از طریق ذخیرهسازی نتایج فراخوانی تابع بر اساس ورودی آنها استفاده میشود. در زمینه انتخابگرهای Redux، حافظهسازی میتواند عملکرد را با اطمینان از اینکه انتخابکنندهها تنها زمانی که ورودی (وضعیت)شان تغییر میکند، دوباره محاسبه میکنند، بهبود بخشد.
میتوانید از کتابخانههایی مانند reselect
برای حافظهگذاری در انتخابگرهای Redux استفاده کنید:
npm install reselect
مثال استفاده از reselect
برای حافظه:
import { createSelector } from 'reselect'; // Selectors const getTodos = (state) => state.todos; const getVisibilityFilter = (state) => state.visibilityFilter; // Memoized selector to get visible todos const getVisibleTodos = createSelector( [getTodos, getVisibilityFilter], (todos, visibilityFilter) => { switch (visibilityFilter) { case 'SHOW_COMPLETED': return todos.filter(todo => todo.completed); case 'SHOW_ACTIVE': return todos.filter(todo => !todo.completed); case 'SHOW_ALL': default: return todos; } } );
در این مثال:
createSelector
از reselect
یک انتخابگر ذخیره شده ایجاد می کند که getTodos
و getVisibilityFilter
به عنوان انتخابگر ورودی می گیرد.
تابع انتخابگر کارهای فیلتر شده را بر اساس visibilityFilter
محاسبه می کند و نتیجه را تا زمانی که انتخابگرهای ورودی تغییر کنند در حافظه پنهان ذخیره می کند.
نحوه اتصال React Components به Redux
اتصال اجزای React به Redux یک تکنیک اساسی برای مدیریت کارآمد وضعیت برنامه در پروژه های مبتنی بر React است. Redux به عنوان یک فروشگاه متمرکز عمل می کند که کل وضعیت برنامه شما را نگه می دارد و آن را برای هر مؤلفه ای که به آن نیاز دارد قابل دسترسی است.
تابع connect
از کتابخانه react-redux
در برنامههای React که از Redux برای مدیریت حالت استفاده میکنند، تابع connect
از کتابخانه react-redux
برای اتصال اجزای React به فروشگاه Redux استفاده میشود. این روشی را برای تزریق وضعیت Redux و عملکردهای ارسال کنش (Dispatcher) به اجزای شما ارائه می دهد.
نحوه استفاده از connect
این صورت است:
import React from 'react'; import { connect } from 'react-redux'; // Define a React component const Counter = ({ count, increment, decrement }) => ( <div> <p>Count: {count}</p> <button onClick={increment}>Increment</button> <button onClick={decrement}>Decrement</button> </div> ); // Map Redux state to component props const mapStateToProps = (state) => ({ count: state.count }); // Map dispatching actions to component props const mapDispatchToProps = { increment: () => ({ type: 'INCREMENT' }), decrement: () => ({ type: 'DECREMENT' }) }; // Connect component to Redux store export default connect(mapStateToProps, mapDispatchToProps)(Counter);
وضعیت نقشه برداری و ارسال به Props
mapStateToProps
: این تابع وضعیت فروشگاه Redux را به اجزای React شما ترسیم می کند. حالت Redux را به عنوان آرگومان می گیرد و یک شی را برمی گرداند. هر فیلد در آبجکت برگشتی به یک تکیه گاه برای جزء متصل تبدیل می شود.
mapDispatchToProps
: این تابع اقدامات ارسال را به props کامپوننت React شما ترسیم می کند. این می تواند یک شی باشد که در آن هر فیلد یک تابع ایجاد کننده عمل است، یا تابعی که dispatch
به عنوان آرگومان دریافت می کند و یک شی را برمی گرداند. هر سازنده اکشن به طور خودکار با dispatch
بسته می شود تا بتوان آنها را مستقیماً فراخوانی کرد.
در مثال:
mapStateToProps
فیلد count
را از حالت Redux ( state.count
) به قسمت count
جزء Counter
ترسیم می کند.
mapDispatchToProps
اقدامات increment
و decrement
به غرفه ها نقشه می کند ، پس با کلیک بر روی دکمه ها در مؤلفه Counter
، اقدامات مربوطه را ارسال می کند ( { type: 'INCREMENT' }
و { type: 'DECREMENT' }
).
با استفاده از اجزای متصل در برنامه خود
هنگامی که یک مؤلفه با استفاده از connect
به فروشگاه Redux متصل شد ، می تواند به حالت Redux و اقدامات اعزام از طریق غرفه ها دسترسی پیدا کند. در اینجا نحوه استفاده از مؤلفه های متصل در برنامه خود آورده شده است:
import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import { createStore } from 'redux'; import rootReducer from './reducers'; // Import your root reducer import App from './App'; // Import your connected component // Create Redux store with root reducer const store = createStore(rootReducer); // Render the App component inside the Provider ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') );
در این تنظیم:
Provider
یک مؤلفه از react-redux
است که باعث می شود فروشگاه Redux در دسترس هر مؤلفه تو در تو در توجیه باشد که با استفاده از connect
متصل شده اند.
store
با استفاده از createStore
ایجاد شده و با یک کاهش دهنده ریشه ( rootReducer
) ترکیب می شود که تمام کاهش دهنده های شما را در یک ترکیب می کند.
با بسته بندی مؤلفه سطح بالا ( App
در این حالت) با Provider
و عبور از فروشگاه Redux به عنوان یک غرفه ، تمام مؤلفه های متصل در برنامه شما می توانند به فروشگاه Redux دسترسی پیدا کرده و از طریق غرفه ها با آن ارتباط برقرار کنند ( mapStateToProps
و نقشه های mapDispatchToProps
).
تکنیک های پیشرفته جریان داده Redux
تکنیک های پیشرفته جریان داده Redux براساس اصول اساسی مدیریت حالت در برنامه های پیچیده گسترش می یابد. این تکنیک ها فراتر از اقدامات و کاهش دهنده های اساسی است و مفاهیمی مانند میان افزار ، انتخاب کنندگان و اقدامات ناهمزمان را معرفی می کند.
اقدامات ناهمزمان (Redux Thunk ، Redux Saga)
در Redux ، انجام اقدامات ناهمزمان شامل مدیریت اقدامات است که عوارض جانبی دارند ، مانند واکشی داده ها از سرور یا به روزرسانی حالت غیر همزمان. Redux چندین راه حل میان افزار را برای رسیدگی به اقدامات ناهمزمان به طور مؤثر ارائه می دهد.
Redux Thunk
Redux Thunk یک واسطه است که به شما امکان می دهد سازندگان اکشن را بنویسید که به جای یک شیء اکشن ، یک تابع را برمی گردانند. این تابع می تواند عملیات ناهمزمان را انجام دهد و با اتمام عملیات ناهمزمان ، اقدامات همزمان همزمان را انجام دهد.
مثال استفاده از Redux Thunk برای اقدامات ناهمزمان:
راه اندازی میان افزار redux thunk :
import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import rootReducer from './reducers'; // Import your root reducer // Create Redux store with thunk middleware const store = createStore(rootReducer, applyMiddleware(thunk));
سازنده اکشن Async با استفاده از Redux Thunk :
// Action creator function using Redux Thunk const fetchPosts = () => { return async (dispatch) => { dispatch({ type: 'FETCH_POSTS_REQUEST' }); try { const response = await fetch('https://jsonplaceholder.typicode.com/posts'); const posts = await response.json(); dispatch({ type: 'FETCH_POSTS_SUCCESS', payload: posts }); } catch (error) { dispatch({ type: 'FETCH_POSTS_FAILURE', error: error.message }); } }; };
در این مثال:
fetchPosts
یک خالق اکشن است که به جای یک شیء اکشن ، عملکردی را برمی گرداند.
در داخل عملکرد ، می توانید عملیات ناهمزمان (مانند داده های واکشی) و اقدامات اعزام را بر اساس نتیجه انجام دهید.
Redux Thunk Middleware توابع را که توسط سازندگان اکشن بازگردانده می شود ، انجام می دهد و اقدامات ناهمزمان را در Redux امکان پذیر می کند.
حماسه
Redux Saga یکی دیگر از وسایل نقلیه جانبی برای کنترل عوارض جانبی در برنامه های Redux است. از ژنراتورهای ES6 استفاده می کند تا کد ناهمزمان خواندن ، نوشتن و آزمایش را آسانتر کند.
نمونه ای از استفاده از حماسه redux برای انجام اقدامات ناهمزمان:
تنظیم میانی واسطه Redux :
import { createStore, applyMiddleware } from 'redux'; import createSagaMiddleware from 'redux-saga'; import rootReducer from './reducers'; // Import your root reducer import rootSaga from './sagas'; // Import your root saga // Create Redux Saga middleware const sagaMiddleware = createSagaMiddleware(); // Create Redux store with Saga middleware const store = createStore(rootReducer, applyMiddleware(sagaMiddleware)); // Run the root saga sagaMiddleware.run(rootSaga);
مثال حماسه (Rootsaga.js) :
import { all, call, put, takeEvery } from 'redux-saga/effects'; import { fetchPostsSuccess, fetchPostsFailure } from './actions'; // Import your action creators // Worker saga for fetching posts function* fetchPostsSaga() { try { const response = yield call(fetch, 'https://jsonplaceholder.typicode.com/posts'); const posts = yield call([response, 'json']); yield put(fetchPostsSuccess(posts)); } catch (error) { yield put(fetchPostsFailure(error.message)); } } // Watcher saga to listen for FETCH_POSTS_REQUEST action function* watchFetchPosts() { yield takeEvery('FETCH_POSTS_REQUEST', fetchPostsSaga); } // Root saga export default function* rootSaga() { yield all([ watchFetchPosts() // Add more watchers if needed ]); }
در این مثال:
fetchPostsSaga
یک حماسه کارگر است که عملیات ناهمزمان (پست های واکشی) را انجام می دهد.
watchFetchPosts
یک حماسه Watcher است که برای اقدامات خاص ( FETCH_POSTS_REQUEST
) گوش می دهد و حماسه کارگر مربوطه را تحریک می کند.
rootSaga
با استفاده از all
، چندین سگ را ترکیب می کند و آنها را با استفاده از sagaMiddleware.run
اجرا می کند.
Middleware برای گسترش عملکرد Redux
Middleware in Redux راهی برای گسترش قابلیت های فروشگاه Redux مانند اقدامات ورود به سیستم ، انجام عملیات ناهمزمان ، مسیریابی و موارد دیگر فراهم می کند. Middleware بین اعزام یک عمل و لحظه رسیدن به کاهش دهنده قرار دارد و امکان رهگیری و دستکاری در اقدامات را فراهم می کند.
نمونه ای از وسط نرم افزار سفارشی:
const loggerMiddleware = store => next => action => { console.log('Dispatching action:', action); const result = next(action); console.log('New state:', store.getState()); return result; }; // Applying custom middleware to Redux store import { createStore, applyMiddleware } from 'redux'; import rootReducer from './reducers'; // Import your root reducer // Create Redux store with custom middleware const store = createStore(rootReducer, applyMiddleware(loggerMiddleware));
در این مثال:
loggerMiddleware
یک عملکرد میان افزار سفارشی است که هر یک از اقدامات اعزام شده و حالت حاصل را ثبت می کند.
next
تابعی است که توسط redux ارائه می شود که به عمل اجازه می دهد تا به میان افزار بعدی یا کاهش دهنده ادامه یابد.
Middleware Custom با رهگیری اقدامات ، انجام منطق سفارشی و ارسال اختیاری اقدامات جدید یا اصلاح موارد موجود ، عملکرد Redux را تقویت می کند.
بهترین شیوه ها برای مدیریت جریان داده در Redux
Redux یک روش ساختاری برای مدیریت حالت در برنامه های جاوا اسکریپت فراهم می کند ، اما استفاده مؤثر نیاز به پیروی از بهترین شیوه ها دارد. در اینجا توصیه های اصلی من برای مدیریت جریان داده در Redux آورده شده است:
سازماندهی کاهش دهنده ها و اقدامات
ساختار و سازمان پرونده :
نگرانی های جداگانه : برای حفظ وضوح و مدولار ، اقدامات ، کاهش دهنده ها و انتخاب کنندگان را در پرونده های جداگانه نگه دارید.
ساختار مبتنی بر ویژگی : اقدامات مرتبط با گروه و کاهش دهنده ها بر اساس ویژگی ها و نه انواع.
src/ ├── actions/ │ ├── todosActions.js │ └── userActions.js ├── reducers/ │ ├── todosReducer.js │ └── userReducer.js ├── selectors/ │ ├── todosSelectors.js │ └── userSelectors.js └── store.js
انواع عمل :
ثابت : برای جلوگیری از علامت گذاری و اطمینان از قوام ، از ثابت یا عناصر برای انواع اقدامات استفاده کنید.
// Action types export const ADD_TODO = 'ADD_TODO'; export const DELETE_TODO = 'DELETE_TODO';
ترکیب کاهش دهنده :
ترکیب کننده ها را ترکیب کنید : از combineReducers
از Redux استفاده کنید تا چندین کاهش دهنده را در یک کاهش دهنده ریشه ترکیب کنید.
import { combineReducers } from 'redux'; import todosReducer from './todosReducer'; import userReducer from './userReducer'; const rootReducer = combineReducers({ todos: todosReducer, user: userReducer }); export default rootReducer;
به روزرسانی های حالت تغییر ناپذیر
تغییر ناپذیری با اپراتور گسترش :
از اپراتور گسترش استفاده کنید ( ...
) : هنگام به روزرسانی حالت ، اشیاء یا آرایه های جدید ایجاد کنید تا تغییر ناپذیری را حفظ کنید.
// Updating an array in Redux state const todosReducer = (state = initialState, action) => { switch (action.type) { case ADD_TODO: return { ...state, todos: [ ...state.todos, { id: action.id, text: action.text, completed: false } ] }; case TOGGLE_TODO: return { ...state, todos: state.todos.map(todo => (todo.id === action.id) ? { ...todo, completed: !todo.completed } : todo ) }; default: return state; } };
کتابخانه های تغییر ناپذیر :
تغییر ناپذیر. js : استفاده از کتابخانه هایی مانند تغییر ناپذیر. JS را برای ساختار داده های پیچیده تر برای اجرای تغییر ناپذیری و بهینه سازی عملکرد در نظر بگیرید.
import { Map, List } from 'immutable'; const initialState = Map({ todos: List(), user: Map() }); const todosReducer = (state = initialState, action) => { switch (action.type) { case ADD_TODO: return state.update('todos', todos => todos.push(Map({ id: action.id, text: action.text, completed: false }))); case TOGGLE_TODO: return state.update('todos', todos => todos.map(todo => (todo.get('id') === action.id) ? todo.set('completed', !todo.get('completed')) : todo ) ); default: return state; } };
آزمایش برنامه های Redux
آزمایش واحد :
کاهش دهنده ها : برای اطمینان از رسیدگی صحیح آنها و بازگشت حالت مورد انتظار ، کاهش دهنده های آزمایش را انجام می دهند.
describe('todosReducer', () => { it('should handle ADD_TODO', () => { const action = { type: 'ADD_TODO', id: 1, text: 'Test todo' }; const initialState = { todos: [] }; const expectedState = { todos: [{ id: 1, text: 'Test todo', completed: false }] }; expect(todosReducer(initialState, action)).toEqual(expectedState); }); });
تست ادغام :
سازندگان اکشن و Thunks : سازندگان اکشن و Thunks را آزمایش کنید تا تأیید کنند که اقدامات صحیح را ارسال می کنند یا عملیات ناهمزمان را انجام می دهند.
describe('fetchPosts action creator', () => { it('creates FETCH_POSTS_SUCCESS when fetching posts has been done', () => { const expectedActions = [ { type: 'FETCH_POSTS_REQUEST' }, { type: 'FETCH_POSTS_SUCCESS', payload: { /* mocked data */ } } ]; const store = mockStore({ posts: [] }); return store.dispatch(fetchPosts()).then(() => { expect(store.getActions()).toEqual(expectedActions); }); }); });
ادغام با مؤلفه ها :
اجزای متصل : اجزای متصل به آن را با استفاده از redux-mock-store
برای شبیه سازی رفتار فروشگاه Redux آزمایش کنید.
import configureStore from 'redux-mock-store'; import { Provider } from 'react-redux'; import { render } from '@testing-library/react'; import App from './App'; const mockStore = configureStore([]); describe('<App />', () => { it('renders App component', () => { const store = mockStore({ /* mocked state */ }); const { getByText } = render( <Provider store={store}> <App /> </Provider> ); expect(getByText('Welcome to Redux App')).toBeInTheDocument(); }); });
نتیجه
Redux یک راه حل قدرتمند مدیریت دولت را برای برنامه های جاوا اسکریپت ارائه می دهد و روشی قابل پیش بینی و متمرکز برای مدیریت وضعیت برنامه را ارائه می دهد.
این که آیا انجام عملیات ناهمزمان با میان افزار مانند Redux Thunk یا Redux Saga ، یا بهینه سازی مدیریت دولت از طریق شیوه های داده های تغییر ناپذیر ، Redux شما را قادر می سازد تا برنامه های مقیاس پذیر و قابل نگهداری را بسازید.
با تسلط بر این تکنیک ها ، می توانید از Redux برای ساده سازی جریان داده ها ، تقویت عملکرد برنامه و ساده سازی پیچیدگی های مدیریت دولت در توسعه وب مدرن استفاده کنید.
این همه برای این مقاله است! اگر می خواهید مکالمه را ادامه دهید یا سؤال ، پیشنهاد یا بازخورد داشته باشید ، احساس راحتی کنید تا با من در LinkedIn ارتباط برقرار کنید. و اگر از این محتوا لذت بردید ، برای حمایت از ایجاد محتوای سازگار با توسعه دهنده ، قهوه را برای من خریداری کنید .
ارسال نظر