انتقل إلى محتوى الدرس
الدرس 28
دورة ReactJS

إدارة الحالات المركبة عبر خطاف useReducerExtracting Complex State Logic with useReducer

تعلّم تجميع انتقالات الحالة المتشعبة في دالة مخفض reducer نقية باستخدام خطاف useReducer في React، وإرسال أوامر dispatch واضحة، ومتى تتفوق على useState.
أقسام الدرس
6
الأمثلة
4
اللغة
العربية
تاريخ النشر
غير محدد
المشاهدات
0
محتوى الدرس
في هذا الدرس 6تصفّح المواضيع

تظل المكونات البسيطة التي تدير حقل إدخال وحيداً أو مفتاح تبديل واضحة ومقروءة عند استخدام خطاف useState. لكن مع نمو المزايا التفاعلية — مثل لوحة مهام تدعم الإضافة، وتعديل النص، وتبديل الإنجاز، وحذف المكتمل — تتبعثر استدعاءات تحديث الحالة عبر عشرات الدوال الفرعية بحيث يصعب حصر جميع المسارات التي تتغير فيها البيانات بنظرة واحدة.

عندما تزدحم معالجات الأحداث بتفاصيل نسخ المصفوفات ودمج الكائنات، تتسلل الأخطاء كلما نسي أحد المعالجات تحديث حقل مرتبط بآخر. تعالج React هذا الازدحام بفصل منطق تحديث الحالة بالكامل في دالة موحدة خارج المكون تُسمى دالة المخفض (Reducer).

بدلاً من تعديل الحالة مباشرة داخل الأزرار، ترسل معالجات الأحداث كائن أمر (Action Object) عبر دالة الإرسال. يمثل كائن الأمر سجلاً نصياً صريحاً يحمل خاصية type لوصف الحدث الذي وقع مثل { type: 'incremented' } أو { type: 'reset' }.

تمرر مكتبة React الحالة الراهنة state مع كائن الأمر action إلى دالة reducer(state, action) التي تتولى حساب الحالة التالية وإرجاعها بأمان.

HTML
function counterReducer(state, action) {
  if (action.type === 'incremented') {
    return { count: state.count + 1 };
  }
  if (action.type === 'reset') {
    return { count: 0 };
  }
  throw new Error('Unknown: ' + action.type);
}

يتم ربط خطاف useReducer داخل المكون عبر ثلاث خطوات عملية منظمة: استيراد { useReducer } من حزمة 'react'، ثم استدعاء const [state, dispatch] = useReducer(reducer, initialState) في المستوى الأعلى للمكون، وأخيراً استبدال دوال الضبط المباشرة باستدعاءات dispatch(action).

يستقبل الخطاف معاملين هما مرجع دالة المخفض والقيمة الابتدائية للحالة، ويعيد مصفوفة ثنائية تضم القيمة الحالية للقراءة ودالة الإرسال لإطلاق التحديثات.

مخطط يوضح المراحل الأربع لدورة خطاف useReducer من حدث المستخدم وإرسال الأمر إلى دالة المخفض وإعادة الرسم
HTML
import { useReducer } from 'react';

function CounterPanel() {
  const [state, dispatch] = useReducer(reducer, {
    seats: 2,
  });
  return (
    <button onClick={() => dispatch({ type: 'add' })}>
      Seats: {state.seats}
    </button>
  );
}

لأن دوال المخفض تعمل أثناء مرحلة حساب العرض، يجب أن تكون دالة نقية تماماً (Pure Function): أي تُرجع نفس المخرجات دائماً لنفس المدخلات دون تعديل الكائنات الأصلية مباشرة أو استدعاء طلبات خارجية. جرى العرف الهندسي على تنظيمها بكتلة switch (action.type) مع إحاطة كل فرع بأقواس معقوفة لمنع تضارب المتغيرات المحلية، وختمها بفرع default يطلق خطأً صريحاً يكشف أخطاء التسمية فوراً.

HTML
function tasksReducer(tasks, action) {
  switch (action.type) {
    case 'added':
      return [...tasks, action.item];
    case 'deleted':
      return tasks.filter((t) => t.id !== action.id);
    default:
      throw new Error('Unknown: ' + action.type);
  }
}

يعبر كائن الأمر المتقن عن تفاعل مستخدم متكامل واحد حتى لو أدى ذلك التفاعل إلى تحديث عدة حقول في آنٍ معاً. فعند نقر زر تفريغ السلة مثلاً، نرسل أمراً واحداً مثل { type: 'cart_cleared' } يصفر المنتجات وكود الخصم معاً داخل فرع واحد بدلاً من ثلاثة أوامر منفصلة. وتُرفق البيانات الإضافية اللازمة — وتُعرف بحمولة الأمر (Payload) — بجانب خاصية type مباشرة.

HTML
dispatch({
  type: 'item_quantity_updated',
  itemId: 104,
  nextQty: 3,
});

لا يلغي أحد الخطافين الآخر، بل يختار مهندس React الأداة الأنسب لطبيعة المكون؛ فخطاف useState مثالي للقيم المستقلة البسيطة، بينما يتألق useReducer عندما تتشابك عدة حقول في عملية تحديث واحدة، أو تحتاج لتتبع سبب كل انتقال بدقة، أو ترغب في اختبار منطق الحالة منفرداً كدالة JavaScript قياسية. يوضح الجدول التالي معايير المفاضلة:

معيار المقارنةخطاف useStateخطاف useReducer
حجم الشفرة المبدئيمختصر جداً للقيم الفردية المستقلةيتطلب تعريف دالة المخفض وكائنات الأوامر
الوضوح مع نمو التعقيدتتشتت التحديثات عند كثرة معالجات الأحداثيجمع كل مسارات الانتقال في مكان مركزي واحد
سهولة التتبع والتشخيصيكشف القيمة الجديدة دون توضيح سبب التغييريوثق نوع الأمر وحمولته بدقة لكل انتقال
الاختبار البرمجي المنعزلمرتبط بتشغيل المكون ورسم الواجهةدالة نقية تُختبر مباشرة بمدخلات ومخرجات صريحة
خلاصة المعرفة ومحطة الانتقال

ملخص الدرس

حصاد الدرس

مراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي

ماذا تعلّمت في هذا الدرس؟

تعلّمت في هذا الدرس كيفية استخلاص تحديثات الحالة المزدحمة في دالة مخفض نقية، وتشغيل خطاف useReducer مع دالة الإرسال dispatch، وتصميم أوامر واضحة تعبر عن تفاعل المستخدم دون تعديل مباشر للكائنات، والمفاضلة الهندسية الدقيقة بين useState وuseReducer. الخطوة التالية: انتقل الآن إلى الدرس رقم 29 «مشاركة البيانات بعمق عبر createContext وuseContext» لمواصلة البناء التراكمي المتدرج في مسار React الحديث.

مشاركة

هل كان هذا الدرس مفيدًا؟

جارٍ تحميل الآراء…

ابنِ لغتك البرمجية

المصطلحات4

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 4 مفهومةأول بطاقة، أول خطوة
01 Reducer Function دالة المخفض
دالة JavaScript نقية تستقبل الحالة الراهنة وكائن الأمر لتحسب وتُرجع الحالة الجديدة دون آثار جانبية.
للمراجعة
02 Action Object كائن الأمر
كائن قياسي يحمل خاصية نصية type تصف التفاعل الذي أجراه المستخدم ليتم التعامل معه في المخفض.
للمراجعة
03 Dispatch إرسال الأمر
الدالة التي يعيدها خطاف useReducer لإرسال كائن الأمر إلى دالة المخفض وجدولة إعادة رسم الواجهة.
للمراجعة
04 Action Payload حمولة الأمر
الحقول الإضافية المرفقة داخل كائن الأمر لحمل البيانات التفصيلية اللازمة لحساب التحديث الجديد.
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

حروف قليلة. معنى كامل.

الاختصارات4

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 4 مفهومةأول بطاقة، أول خطوة
01 UI UI
User Interface
عناصر الشاشة المرئية التي تكتفي معالجاتها بإرسال أوامر التفاعل بدلاً من تعديل الحالة يدوياً.
للمراجعة
02 CRUD CRUD
Create, Read, Update, Delete
العمليات الأربع القياسية لإدارة القوائم والتي تدفع غالباً لتوحيد منطق الحالة داخل دالة مخفض.
للمراجعة
03 API API
Application Programming Interface
العقد البرمجي المحدد للمدخلات والمخرجات التي يوفرها خطاف مثل useReducer داخل مكتبة React.
للمراجعة
04 DOM DOM
Document Object Model
شجرة عناصر المتصفح التي تحدثها React تلقائياً فور إرجاع دالة المخفض للحالة الجديدة.
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

من الفهم للتطبيق

مهامك قبل الاختبار

خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.

0/2مهام منجزة
  1. افتح مثال لوحة المهام في محرر التجريب وأضف فرع cleared_completed داخل دالة المخفض لتصفية المهام غير المنجزة واربطه بزر إرسال جديد.

  2. جرّب مثال سلة الدفع في محرر التجريب، زد عدد الرخص وطبّق القسيمة ثم اختبر كيف يعيد أمر cart_reset جميع الحقول لحالتها الابتدائية دفعة واحدة.

تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.

مساحة التحدي

اختبر فهمك.
ووصلها للإتقان.

كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.

10أسئلة 2أنواع تحديات 100%هدف الإتقان
تصحيح تلقائي. فرص بلا حدود.

أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.

الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.

لمحة عن التحدي10 أسئلة تنتظرك
01

ما المشكلة المعمارية التي يعالجها خطاف useReducer عند تضخم المكونات التفاعلية؟

يوحد خطاف useReducer منطق تحديثات الحالة المبعثر عبر عدة معالجات أحداث في دالة نقية مركزية واحدة.

02

ما المعاملان اللذان تمررهما مكتبة React إلى دالة المخفض عند كل استدعاء إرسال؟

تستقبل دالة المخفض دائماً الحالة الحالية state وكائن الأمر action لتعيد الحالة التالية.

03

بدلاً من تعديل الحالة مباشرة داخل الأزرار، ترسل دالة dispatch كائن أمر يصف ماذا فعل المستخدم.

صواب؛ تكتفي معالجات الأحداث بإرسال وصف التفاعل بينما تتكفل دالة المخفض بحساب شكل الحالة الجديد.

04

ماذا يعيد استدعاء خطاف useReducer(reducer, initialState) داخل المكون؟

يعيد خطاف useReducer مصفوفة من عنصرين هما القيمة الحالية للحالة ودالة الإرسال dispatch.

05

يُمنع استخدام useState لحقل نص مؤقت داخل أي مكون يعتمد على useReducer لقائمته الرئيسية.

خطأ؛ فالجمع بين useReducer للبيانات المركبة وuseState لحقول الكتابة المحلية المؤقتة ممارسة سليمة وشائعة.

06

لماذا يجب أن تظل دالة المخفض reducer دالة نقية تماماً دون تعديل الكائنات الأصلية؟

تعمل دوال المخفض أثناء مرحلة العرض، وتعديل الكائنات في مكانها يفسد رصد التغييرات وفحوصات الوضع الصارم.

07

ما الممارسة الهندسية الموصى بها في فرع default الأخير داخل جملة switch في المخفض؟

إطلاق خطأ صريح عبر throw new Error يكشف الأخطاء الإملائية في أسماء الأوامر فور وقوعها.

08

عندما تؤدي نقرة زر واحدة إلى تصفير ثلاثة حقول مترابطة، يُفضل تمثيلها بأمر واحد شامل بدلاً من ثلاثة أوامر متفرقة.

صواب؛ يجب أن يمثل الأمر الواحد تفاعل مستخدم متكاملاً يحدث جميع الحقول المرتبطة معاً بأمان.

09

ما اسم الخاصية القياسي المتعارف عليه لتحديد نوع الحدث داخل كائن الأمر؟

تعتمد كائنات الأوامر في React على خاصية نصية قياسية باسم type لتعريف نوع الحدث.

10

أي الحالات التالية تعد المرشح الأقوى لاختيار useReducer بدلاً من useState؟

يتفوق useReducer عندما تتغير عدة حقول مترابطة عبر أوامر متعددة وتحتاج لاختبار منطقها كدالة مستقلة.