useReducer في React: بديل متقدم لـ useState

عندما تصبح الحالة معقدة أو تتغير بعدة طرق مختلفة، قد يصبح useState غير منظم. هنا يأتي دور useReducer.

ما هو useReducer في React؟

useReducer هو Hook يسمح لك بإدارة الحالة عبر دالة واحدة (reducer) تتحكم في كل التغييرات باستخدام actions.

التعريف البسيط: useReducer = useState لكن مع منطق تحديث مركزي.

مثال بسيط: عدّاد باستخدام useReducer

import { useReducer } from "react";

function reducer(state, action) {
  switch (action.type) {
    case "increment":
      return { count: state.count + 1 };
    case "decrement":
      return { count: state.count - 1 };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  return (
    <div>
      <p>العدد: {state.count}</p>
      <button onClick={() => dispatch({ type: "increment" })}>زيادة</button>
      <button onClick={() => dispatch({ type: "decrement" })}>نقصان</button>
    </div>
  );
}

هنا نستخدم dispatch لإرسال action، وreducer يحدد كيف تتغير الحالة.

الفكرة: بدل أن نكتب setCount في أماكن متعددة، نرسل أوامر واضحة مثل increment و decrement. هذه الأوامر تُعالج داخل reducer، فيصبح من السهل تتبع منطق التحديث.

شرح سريع لمسار التنفيذ: عند الضغط على زر \"زيادة\" يتم استدعاء dispatch مع type: \"increment\". React يمرّر هذا الـ action إلى reducer، فيعود بحالة جديدة مع قيمة count محدثة. بعدها يعيد React الرندر ويظهر العدد الجديد.

لماذا useReducer مفيد؟

  • يجمع كل منطق التحديث في مكان واحد.
  • يسهل قراءة التغييرات خصوصًا مع الحالات الكبيرة.
  • يشبه Redux لكن بدون تعقيد إضافي.

مثال عملي: نموذج تسجيل بسيط

import { useReducer } from "react";

const initialState = { name: "", email: "" };

function reducer(state, action) {
  switch (action.type) {
    case "setName":
      return { ...state, name: action.value };
    case "setEmail":
      return { ...state, email: action.value };
    case "reset":
      return initialState;
    default:
      return state;
  }
}

function RegisterForm() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <form>
      <input
        value={state.name}
        onChange={(e) => dispatch({ type: "setName", value: e.target.value })}
      />
      <input
        value={state.email}
        onChange={(e) => dispatch({ type: "setEmail", value: e.target.value })}
      />
      <button type="button" onClick={() => dispatch({ type: "reset" })}>
        إعادة تعيين
      </button>
    </form>
  );
}

استخدمنا useReducer لإدارة حقول النموذج بشكل منظم.

كل حقل يرسل action محددة لتحديث جزء من الحالة فقط. وعند الضغط على \"إعادة تعيين\" نعيد الحالة كاملة إلى القيمة الابتدائية، بدل أن نعيد ضبط كل input يدويًا.

لاحظ أن الحالة هنا كائن واحد يحتوي على name و email. عند تغيير حقل الاسم، نعيد نسخة من الحالة مع تحديث الاسم فقط باستخدام { ...state, name: action.value }. هذا الأسلوب يحافظ على بقية القيم بدون فقدانها.

استخدام reset يجعل من السهل إعادة النموذج لوضعه الأصلي بعد الإرسال أو عند الضغط على زر إعادة التعيين.

أخطاء شائعة

  • استخدام useReducer في حالات بسيطة جدًا.
  • نسيان default في reducer فيسبب أخطاء غير متوقعة.
  • تغيير state مباشرة داخل reducer (يجب إرجاع نسخة جديدة).

الأسئلة الشائعة — FAQ

ما هو useReducer في React؟

Hook لإدارة الحالة المعقدة عبر reducer و actions.

متى أستخدم useReducer بدل useState؟

عندما تكون الحالة معقدة أو تحتوي تحديثات عديدة مترابطة.

ما الفرق بين reducer و state؟

reducer هو الدالة التي تحدد التغيير، بينما state هي البيانات.

هل useReducer مشابه لـ Redux؟

نعم من حيث الفكرة، لكنه أبسط وموجود داخل React.

كيف أرسل action إلى reducer؟

باستخدام dispatch مثل dispatch({ type: "increment" }).

التالي: سننتقل لدرس Custom Hooks لبناء Hooks خاصة.
المحرر الذكي

اكتب الكود وشاهد النتيجة فوراً

جرب الآن مجاناً
قناة ديف عربي

تابع أحدث الدروس والتحديثات مباشرة على واتساب

انضم الآن