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

دمج useReducer مع Context لهندسة حالة قابلة للتوسعScaling State Architecture with Reducer and Context

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

ينجح خطاف useReducer بمفرده في جمع قواعد تحديث الحالة المعقدة داخل دالة مخفض واحدة متوقعة السلوك، لكن مصفوفة الحالة ودالة dispatch تظلان محصورتين داخل المكون العلوي الذي استدعى الخطاف. وفي لوحات المهام متعددة المستويات يعود عبء التمرير المتسلسل للبيانات ودوال الأحداث عبر الحاويات الوسيطة.

إن الجمع الهندسي بين useReducer والسياق Context يحل شقي المعادلة معاً؛ فالمخفض يضبط كيف تنتقل الحالة بأمان، بينما يوصل السياق البيانات ودالة الإرسال إلى أي مكون عميق مباشرة دون إزعاج المكونات الوسيطة.

بدلاً من دمج المصفوفة ودالة الإرسال في كائن سياق واحد، يوصي التوثيق الهندسي الرسمي لمكتبة React بإنشاء سياقين منفصلين تماماً:

  • سياق القراءة TasksContext: يزود المكونات العارضة والعدادات بمصفوفة المهام الحالية.
  • سياق الإرسال TasksDispatchContext: يزود النماذج وأزرار التحكم بدالة dispatch لإرسال أوامر الإضافة والتبديل والحذف.

وبما أن React تضمن ثبات هوية دالة dispatch عبر التصييرات المتتالية، فإن المكونات التي تستهلك سياق الإرسال فقط مثل نموذج إضافة مهمة جديدة لا تضطر لإعادة تصيير نفسها عند تبديل حالة مهمة أخرى في القائمة.

HTML
const TasksContext = createContext(null);
const TasksDispatchContext = createContext(null);

function DualWire({ tasks, dispatch, children }) {
  return (
    <TasksContext.Provider value={tasks}>
      <TasksDispatchContext.Provider value={dispatch}>
        {children}
      </TasksDispatchContext.Provider>
    </TasksContext.Provider>
  );
}

لإبقاء المكون الجذري App نظيفاً ومختصراً، انقل كلاً من السياقين ودالة المخفض tasksReducer والبيانات الابتدائية ومكون التغليف TasksProvider({ children }) إلى ملف وحدة برمجية مستقلة مثل TasksContext.jsx.

داخل TasksProvider يتولى استدعاء واحد لخطاف useReducer إدارة دورة حياة البيانات وتغذية المزودين المتداخلين معاً، فتتعامل بقية ملفات المشروع مع <TasksProvider> كوحدة جاهزة مكتفية ذاتياً.

الركائز المعمارية الثلاث لدمج دالة المخفض مع سياق قراءة المهام وسياق إرسال الأوامر المستقل
HTML
export function TasksProvider({ children }) {
  const [tasks, dispatch] = useReducer(reducer, init);
  return (
    <TasksContext.Provider value={tasks}>
      <TasksDispatchContext.Provider value={dispatch}>
        {children}
      </TasksDispatchContext.Provider>
    </TasksContext.Provider>
  );
}

بمجرد تغليف شجرة الميزة بوسم <TasksProvider>، يستطيع أي مكون فرعي عميق إرسال تحديثاته باستقلالية تامة. يقرأ شريط الإضافة useContext(TasksDispatchContext) لإرسال أمر added، بينما يرسل كل سطر مهمة أوامر toggled أو deleted مباشرة بمعرف المهمة id.

لاحظ التوازن الهندسي الدقيق هنا: تبقى مسودة النص المؤقتة التي يكتبها المستخدم داخل حقل الإدخال في useState محلي داخل شريط الإضافة، بينما تنتقل قائمة المهام المشتركة فقط إلى سياق المخفض عند الضغط على زر الإضافة.

HTML
function AddTaskButton() {
  const dispatch = useContext(TasksDispatchContext);
  function handleAdd() {
    dispatch({
      type: 'added',
      id: Date.now(),
      title: 'Review Context Pattern',
    });
  }
  return <button onClick={handleAdd}>Add Task</button>;
}

تأمل التحول الذي يطرأ على ملفات الواجهة بعد نقل حالة النطاق المشتركة إلى وحدة المخفض والسياق: لم تعد مكونات التخطيط مثل App وWorkspaceLayout تعرّف عشرات دوال المعالجة أو تمرر خصائص لا تستخدمها بنفسها.

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

HTML
function TaskSummary() {
  const tasks = useContext(TasksContext);
  const done = tasks.filter((t) => t.done).length;
  return (
    <header className="summary">
      <h4>Completed: {done} / {tasks.length}</h4>
    </header>
  );
}

بعد إتقانك لأنماط الحالة الأساسية في React، اتبع سلم قرارات إدارة الحالة بتدرج هندسي منضبط بدلاً من القفز فوراً إلى المخفض والسياق في المكونات البسيطة: ابدأ دائماً بـ useState المحلي داخل المكون الواحد، ثم ارفع الحالة لأقرب أب مشترك عند تنسيق مكونين متجاورين، وانتقل إلى useReducer عند تشعب أوامر التحديث، وادمج useReducer مع سياقي القراءة والإرسال عندما تشترك شجرة عميقة في قراءة وتعديل تلك الحالة. يلخص الجدول التالي معايير الاختيار:

مرحلة التدرجنمط إدارة الحالة في Reactمتى نختاره هندسياً
المرحلة 1 — مكون منفردحالة محلية بـ useStateزر تبديل مستقل أو نص حقل مؤقت داخل مكون واحد
المرحلة 2 — تنسيق شقيقينرفع الحالة للأب وتمرير Propsمكونان متجاوران يتشاركان قيمة واحدة عبر أبيهما المباشر
المرحلة 3 — انتقالات متشعبةمخفض محلي بـ useReducerمكون واحد يدير عدة أوامر مترابطة لتحديث بياناته
المرحلة 4 — نطاق عميق مشتركدمج useReducer مع سياقينشجرة مكونات عميقة تقرأ البيانات وترسل أوامر التعديل مباشرة
خلاصة المعرفة ومحطة الانتقال

ملخص الدرس

حصاد الدرس

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

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

تعلمت في هذا الدرس كيف يقضي دمج useReducer مع السياق على تشتت دوال التعديل والتمرير المتسلسل للخصائص، وفصلت سياق القراءة TasksContext عن سياق الإرسال TasksDispatchContext داخل مكون مزود متكامل، وأتقنت سلم التدرج الهندسي لإدارة الحالة. الخطوة التالية: انتقل الآن إلى الدرس رقم 32 «حفظ القيم المتغيرة دون إعادة تصيير عبر useRef» لمواصلة البناء التراكمي المتدرج في مسار React الحديث.

مشاركة

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

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

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

المصطلحات4

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

0 / 4 مفهومةأول بطاقة، أول خطوة
01 State Context سياق قراءة الحالة
سياق مخصص يزود مكونات العرض بالقيمة الحالية لبيانات الحالة مثل مصفوفة المهام للقراءة فقط.
للمراجعة
02 Dispatch Context سياق إرسال الأوامر
سياق مستقل يوفر دالة الإرسال الخاصة بالمخفض لتمكين المكونات الفرعية العميقة من إطلاق أوامر التحديث.
للمراجعة
03 State Module وحدة الحالة المتكاملة
ملف برمجي مكتفٍ ذاتياً يجمع دالة المخفض والحالة الابتدائية وكائني السياق ومكون المزود في مكان واحد.
للمراجعة
04 State Scaling Ladder سلم تدرج الحالة
المنهجية الهندسية المتدرجة من useState المحلي إلى رفع الحالة ثم المخفض وصولاً إلى دمج المخفض مع السياق.
للمراجعة

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

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

الاختصارات4

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

0 / 4 مفهومةأول بطاقة، أول خطوة
01 CRUD CRUD
Create, Read, Update, Delete
العمليات الأربع الأساسية لإدارة البيانات من إنشاء وقراءة وتحديث وحذف والتي تمثلها أوامر المخفض.
للمراجعة
02 UI UI
User Interface
مكونات العرض التصريحية التي تبقى مختصرة ونظيفة بعد انتقال قواعد تحديث البيانات إلى وحدة المزود.
للمراجعة
03 API API
Application Programming Interface
الواجهة البرمجية الواضحة التي تصدرها وحدة المزود لتتفاعل المكونات عبر سياقي القراءة والإرسال.
للمراجعة
04 SPA SPA
Single-Page Application
تطبيقات الصفحة الواحدة التفاعلية التي تنسق فيها وحدات الحالة المشتركة الشاشات المتعددة دون إعادة تحميل.
للمراجعة

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

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

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

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

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

  2. عدّل مكون TaskSummary في مثال شريط الإنجاز ليحسب ويعرض عدد المهام غير المكتملة المتبقية بجانب المكتملة.

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

مساحة التحدي

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

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

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

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

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

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

ما المشكلة الهندسية التي يحلها دمج خطاف useReducer مع السياق Context؟

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

02

لماذا يوصي توثيق React بفصل TasksContext عن TasksDispatchContext بدلاً من وضعهما في كائن سياق واحد؟

يفصل ذلك القراءة عن الكتابة ويحمي المكونات التي ترسل الأوامر فقط من إعادة التصيير عند تغير مصفوفة المهام.

03

تحافظ دالة dispatch العائدة من useReducer على هوية مرجعية مستقرة عبر التصييرات المتعاقبة.

صواب؛ تضمن React ثبات مرجع دالة dispatch مما يجعل تمريرها في سياق مستقل عالي الكفاءة.

04

ما الذي يحتويه مكون التغليف المتكامل TasksProvider({ children }) داخله؟

يستدعي TasksProvider خطاف useReducer ويغلف {children} بمزودي القراءة والإرسال معاً.

05

عند استخدام TasksProvider يجب تخزين النص المؤقت أثناء الكتابة داخل حقل الإدخال في المخفض العام دائماً.

خطأ؛ فالنص المؤقت أثناء الكتابة يبقى في useState محلي داخل النموذج، ثم يُرسل أمر الإضافة عند الاعتماد فقط.

06

كيف يحذف مكون زر عميق مهمة محددة دون أن يستلم خاصية onDelete من المكون الأب؟

يقرأ دالة dispatch عبر useContext(TasksDispatchContext) ويستدعيها بكائن الأمر ومعرف المهمة.

07

يتيح نقل انتقالات الحالة المشتركة إلى وحدة المخفض والسياق تفرغ المكونات الوسيطة لهيكلة الواجهة بنظافة.

صواب؛ إذ تتوقف مكونات التخطيط الوسيطة عن العمل كممرات لتمرير بيانات ودوال لا تخصها.

08

كيف يعرض مكون TaskSummary عدد المهام المكتملة عند قراءة مصفوفة المهام من TasksContext؟

يشتق العدد مباشرة أثناء العرض باستخدام tasks.filter(t => t.done).length دون حالة إضافية مكررة.

09

وفق سلم قرارات إدارة الحالة، ما الأداة التي تبدأ بها لمفتاح تبديل بسيط داخل مكون منفرد واحد؟

نبدأ دائماً بخطاف useState المحلي البسيط داخل المكون ولا نترقى إلا عند ظهور حاجة فعلية للمشاركة أو التشعب.

10

عندما يحتاج مكونان شقيقان متجاوران لمشاركة قيمة بسيطة واحدة، فإن رفع الحالة لأبيهما المباشر أبسط من إنشاء سياق جديد.

صواب؛ فرفع الحالة للأب القريب وتمريرها عبر Props هو الحل الأنظف والأبسط للمكونات المتجاورة.