الدرس السابع عشر: إدارة الحالة المتقدمة باستخدام useReducer
في هذا الدرس، سنتعرف على useReducer، وهو React Hook يُستخدم لإدارة الحالة في المكونات، خاصة عندما تكون الحالة معقدة أو تتطلب تغييرات متعددة تعتمد على نوع من الأحداث. سنتعرف على الفرق بين useState و useReducer، وكيفية استخدام useReducer لإدارة الحالة المتقدمة، وسنقوم بتطبيق useReducer لإدارة حالة تطبيق يحتوي على عمليات متعددة.
1. الفرق بين useState و useReducer
useState:
useStateهو React Hook يُستخدم لإدارة الحالة البسيطة، مثل الأرقام أو النصوص أو القيم المنطقية (boolean). يتم استخدامه عادةً عند التعامل مع حالات قليلة التغيير.useStateمثالي عندما يكون لديك حالة واحدة أو حالتان بسيطتان ولا تحتاج إلى منطق معقد لتغيير الحالة.
useReducer:
useReducerهو React Hook يُستخدم لإدارة الحالات الأكثر تعقيدًا التي تتطلب تحديثات متعددة بناءً على أنواع مختلفة من الأحداث.- يُفضل استخدام
useReducerعندما تكون الحالة تحتوي على كائنات أو مصفوفات معقدة أو تحتاج إلى منطق متقدم لتحديثها. - يعمل
useReducerبشكل مشابه لـ Redux في إدارة الحالة، حيث يتم تمرير الـ reducer (دالة تُعالج التحديثات) وأحداث dispatch لتحديث الحالة بناءً على نوع الحدث.
2. كيفية استخدام useReducer لإدارة الحالة المعقدة
الهيكل الأساسي لاستخدام useReducer:
useReducer يتطلب ثلاثة أشياء أساسية:
reducer: دالة تُحدِّث الحالة بناءً على الحدث.initialState: الحالة الأولية (التفاصيل التي تبدأ منها الحالة).dispatch: دالة تُستخدم لإرسال الأحداث إلى الـ reducer لتحديث الحالة.
مثال على استخدام useReducer:
import React, { useReducer } from 'react';
// الحالة الأولية
const initialState = { count: 0 };
// دالة الـ reducer
function counterReducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
case 'reset':
return { count: 0 };
default:
return state;
}
}
function Counter() {
// استخدام useReducer
const [state, dispatch] = useReducer(counterReducer, initialState);
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
<button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</div>
);
}
export default Counter;
الشرح:
counterReducerهو الدالة المسؤولة عن تحديث الحالة بناءً علىaction.type.- عند الضغط على الأزرار، نقوم بإرسال action مع type معين باستخدام
dispatch. useReducerيعيد الحالة الحالية (state) ودالةdispatchالتي تستخدم لإرسال الأحداث.
3. تطبيق useReducer لإدارة حالة تطبيق متعدد العمليات
في بعض التطبيقات التي تحتوي على حالات معقدة تتطلب تحديثات متعددة أو تعتمد على عمليات مختلفة، يمكن أن يكون useReducer الخيار الأمثل. لنأخذ مثالًا على تطبيق يحتوي على عمليات متعددة مثل إضافة عنصر إلى قائمة، إزالة عنصر، وتحديث العنصر.
مثال تطبيقي باستخدام useReducer:
import React, { useReducer } from 'react';
// الحالة الأولية
const initialState = {
items: [],
loading: false,
error: null,
};
// دالة الـ reducer
function appReducer(state, action) {
switch (action.type) {
case 'ADD_ITEM':
return { ...state, items: [...state.items, action.payload] };
case 'REMOVE_ITEM':
return { ...state, items: state.items.filter(item => item.id !== action.payload.id) };
case 'TOGGLE_LOADING':
return { ...state, loading: !state.loading };
case 'SET_ERROR':
return { ...state, error: action.payload };
default:
return state;
}
}
function App() {
const [state, dispatch] = useReducer(appReducer, initialState);
const addItem = (item) => {
dispatch({ type: 'ADD_ITEM', payload: item });
};
const removeItem = (id) => {
dispatch({ type: 'REMOVE_ITEM', payload: { id } });
};
const toggleLoading = () => {
dispatch({ type: 'TOGGLE_LOADING' });
};
return (
<div>
<button onClick={toggleLoading}>
{state.loading ? 'Stop Loading' : 'Start Loading'}
</button>
<div>
{state.loading && <p>Loading...</p>}
{state.error && <p>Error: {state.error}</p>}
<ul>
{state.items.map(item => (
<li key={item.id}>
{item.name}
<button onClick={() => removeItem(item.id)}>Remove</button>
</li>
))}
</ul>
</div>
<button onClick={() => addItem({ id: Date.now(), name: 'New Item' })}>
Add Item
</button>
</div>
);
}
export default App;
الشرح:
appReducerيعالج أربعة أنواع من الأحداث: إضافة عنصر، إزالة عنصر، التبديل بين حالة التحميل، وتعيين خطأ.- كل عملية (إضافة، إزالة، تغيير حالة التحميل، تعيين الخطأ) يتم التعامل معها عن طريق
dispatchمع نوع الحدث المناسب. useReducerيعيد الحالة الحالية ويقوم بتحديث واجهة المستخدم بناءً على التغييرات في هذه الحالة.
4. متى يجب استخدام useReducer؟
يعتبر useReducer مفيدًا في الحالات التي:
- تحتاج فيها إلى تحديثات معقدة لحالة تعتمد على عدة إجراءات أو متغيرات.
- عندما تكون
stateعبارة عن كائن أو مصفوفة تحتوي على بيانات متعددة. - عندما تحتاج إلى التعامل مع حالات متعددة أو منطق معقد داخل reducer.
5. الختام
useReducer هو طريقة قوية لإدارة الحالة في React، خاصة عندما تكون لديك حالات معقدة أو متغيرات متعددة تحتاج إلى تحديثها بناءً على أنواع مختلفة من الأحداث. مقارنة بـ useState، useReducer يوفر حلاً أكثر هيكلية ومرونة لإدارة حالات أكبر وأكثر تعقيدًا.
اكتشاف المزيد من كود التطور
اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.


