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

تخزين الحسابات والدوال عبر useMemo وuseCallbackCaching Calculations and Functions with useMemo and useCallback

احفظ نواتج الحسابات المكلفة وثبّت مراجع الكائنات الديناميكية بخطاف useMemo، وثبّت مراجع الدوال الممررة للمكونات المذكرة بخطاف useCallback وتعرّف على مترجم React الحديث.
أقسام الدرس
6
الأمثلة
3
اللغة
العربية
تاريخ النشر
غير محدد
المشاهدات
0
محتوى الدرس
في هذا الدرس 6تصفّح المواضيع

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

هنا يبرز خطاف useMemo(calculateValue, dependencies) الذي يخزن القيمة الناتجة من عملية حسابية نقية بين مرات التصيير، ولا يعيد حسابها إلا إذا تغير أحد عناصر مصفوفة الاعتماديات وفق فحص Object.is():

HTML
import { useMemo, useState } from 'react';

const visible = useMemo(() => {
  return COURSES.filter((c) =>
    c.title.toLowerCase().includes(query.toLowerCase())
  );
}, [query]);

رأينا في الدرس السابق كيف يكسر الكائن المضمن تغليف React.memo، ولكن ماذا نفعل حين تعتمد قيم ذلك الكائن على حالة داخلية متغيرة فلا يمكن رفعه خارج المكون؟

يحل خطاف useMemo() هذه المشكلة بدقة عبر كتابة useMemo(() => ({ unit, dense }), [unit, dense])؛ إذ يعيد نفس المرجع في الذاكرة طالما لم تتغير عناصر الاعتمادية، مما يحافظ على ثبات المكونات المغلفة بـ memo() واعتماديات useEffect() معاً.

تماماً كما يحدث مع الكائنات المضمنة، فإن تعريف دالة حدث داخل المكون الأب ينشئ مرجع دالة جديداً في كل تصيير؛ فإذا مررت هذه الدالة لمكون فرعي مغلف بـ memo() ستفشل مقارنة المراجع ويعاد رسم الابن في كل مرة.

لتثبيت مرجع الدالة نستخدم خطاف useCallback(fn, dependencies). تذكر القاعدة الفاصلة ببساطة: يخزن useMemo ناتج استدعاء الدالة، بينما يخزن useCallback تعريف الدالة نفسها لتُستدعى لاحقاً عند وقوع الحدث:

مخطط يقارن فحص مصفوفة الاعتماديات وتخزين القيم الحسابية عبر useMemo وتثبيت مراجع الدوال عبر useCallback
HTML
import { memo, useCallback, useState } from 'react';

const handleSelect = useCallback((trackId) => {
  setSelectedId(trackId);
}, []);

// Safe to pass to memoized child:
// <TrackList onSelect={handleSelect} />

انتبه لتفصيل شائع: إذا قرأت دالة الحدث مصفوفة الحالة مباشرة عبر كتابة setTasks([...tasks, next])، فستضطر لإدراج [tasks] في مصفوفة اعتماديات useCallback، مما يعيد إنشاء الدالة عند كل تعديل على المصفوفة!

أما عند استخدام دالة التحديث الوظيفية setTasks((prev) => [...prev, next])، فلا تعود الدالة بحاجة لقراءة المتغير الخارجي، وتفرغ مصفوفة الاعتماديات إلى [] فيبقى مرجع الدالة ثابتاً طوال عمر المكون:

HTML
const toggleDone = useCallback((id) => {
  setItems((prev) =>
    prev.map((it) =>
      it.id === id ? { ...it, done: !it.done } : it
    )
  );
}, []); // Zero state dependencies!

احذر من التذكر المبكر غير المبرر (Premature Memoization). إن تغليف عملية دمج نصين بسيطين بـ useMemo() أو تغليف كل نقرة زر عادية بـ useCallback() يثقل القراءة ويزيد أعباء صيانة الاعتماديات دون أي فرق يشعر به المستخدم.

احتفظ بهذين الخطافين لحالتين واضحتين فقط: العمليات الحسابية الثقيلة التي تستغرق نحو 1 مللي ثانية فأكثر في أداة القياس، أو الكائنات والدوال الممررة لمكونات مغلفة بـ memo() أو داخل مصفوفات اعتماديات الخطافات.

في منظومة React الحديثة، يبرز مترجم React الحديث (React Compiler) كإضافة بناء في Vite تحلل المكونات الملتزمة بقواعد النقاء وتقوم بأتمتة التذكر تلقائياً للقيم المحسوبة وعناصر الواجهة والدوال أثناء عملية البناء، مما يقلص الحاجة لكتابة التغليف اليدوي المتكرر في المشاريع الجديدة مع بقاء فهمك لثبات المراجع أساسياً لتشخيص الحالات الدقيقة. قارن الأدوات الأربع في الجدول التالي:

الأداة البرمجيةما الذي تخزنه بالضبطحالة الاستخدام الهندسية الأساسية
تغليف React.memoمخرجات التصيير لمكون فرعي كاملتخطي رسم المكون الابن عند ثبات جميع خصائصه
خطاف useMemoالقيمة الناتجة عن دالة حسابية نقيةفلترة آلاف السجلات أو تثبيت مراجع الكائنات الديناميكية
خطاف useCallbackمرجع تعريف الدالة نفسها في الذاكرةتمرير دوال أحداث ثابتة للمكونات المغلفة بـ memo
مترجم React Compilerالقيم والدوال وعناصر JSX وقت البناءأتمتة التذكر الدقيق تلقائياً للمكونات النقية
خلاصة المعرفة ومحطة الانتقال

ملخص الدرس

حصاد الدرس

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

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

أتقنت في هذا الدرس تخزين العمليات الحسابية المكلفة وتثبيت الكائنات الديناميكية عبر useMemo، وحفظ مراجع الدوال مع دوال التحديث الوظيفية عبر useCallback، وتجنب التذكر المبكر وفهم دور مترجم React Compiler الحديث. الخطوة التالية: انتقل الآن إلى الدرس رقم 45 «تقسيم الكود والتحميل الكسول عبر React.lazy وSuspense» لمواصلة البناء التراكمي المتدرج في مسار React الحديث.

مشاركة

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

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

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

المصطلحات4

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

0 / 4 مفهومةأول بطاقة، أول خطوة
01 Memoization التذكر المؤقت
تقنية تحسين أداء تحفظ نتيجة عملية نقية مكلفة وتعيدها فوراً عند تكرار نفس المدخلات دون إعادة الحساب.
للمراجعة
02 useMemo خطاف useMemo
خطاف في React يحفظ القيمة المرجعة من دالة حسابية نقية بين مرات التصيير حتى تتغير إحدى اعتمادياته.
للمراجعة
03 useCallback خطاف useCallback
خطاف في React يحفظ مرجع الدالة نفسها عبر مرات التصيير لتمريرها بثبات للمكونات المذكرة أو التأثيرات.
للمراجعة
04 React Compiler مترجم React الحديث
أداة بناء رسمية تحلل المكونات الدالية النقية وتطبق حفظ القيم والمراجع تلقائياً دون تغليف يدوي كثيف.
للمراجعة

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

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

الاختصارات4

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

0 / 4 مفهومةأول بطاقة، أول خطوة
01 CPU CPU
Central Processing Unit
دورات المعالجة التي يوفرها تخطي إعادة فرز وفلترة المصفوفات الكبيرة عند ثبات المدخلات.
للمراجعة
02 HMR HMR
Hot Module Replacement
ميزة التحديث اللحظي للوحدات في Vite أثناء التطوير والتي تعيد تهيئة ذاكرة الخطافات بأمان.
للمراجعة
03 AST AST
Abstract Syntax Tree
شجرة التحليل النحوي للكود التي يفحصها مترجم React وقت البناء لأتمتة التذكر.
للمراجعة
04 UI UI
User Interface
واجهة المستخدم التي تحافظ على سلاستها عند عزل وتخزين الحسابات المشتقة الثقيلة.
للمراجعة

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

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

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

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

0/2مهام منجزة
  1. شغّل مثال CourseExplorer واضغط زر تبديل التخطيط خمس مرات وتأكد أن عداد تشغيل الفلترة يظل ثابتاً ولا يزيد إلا عند الكتابة في حقل البحث.

  2. اضغط زر التبديل لأحد المهام في مثال قائمة المهام وتأكد من بقاء عداد التصيير للصفين الآخرين ثابتاً دون زيادة.

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

مساحة التحدي

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

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

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

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

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

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

ما الفرق الجوهري بين خطاف useMemo وخطاف useCallback؟

يخزن useMemo النتيجة المحسوبة من استدعاء الدالة، بينما يخزن useCallback مرجع تعريف الدالة نفسها.

02

تعمل الدالة الممررة إلى useMemo أثناء طور التصيير ويجب أن تظل دالة نقية خالية من الآثار الجانبية.

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

03

كيف تمنع كائن إعدادات ديناميكياً يعتمد على unit وshowTrend من كسر تغليف React.memo للمكون الفرعي؟

بتغليف إنشاء الكائن داخل useMemo مع تحديد المتغيرين في مصفوفة الاعتماديات.

04

هل يحقق تغليف دالة بـ useCallback تسريعاً في التصيير إذا مُررت فقط لعنصر زر HTML عادي؟

لا؛ فعناصر HTML العادية لا تفحص ثبات المرجع عبر React.memo لذا لا يوفر ذلك أي إعادة تصيير.

05

داخل useCallback، كيف تحدّث مصفوفة الحالة tasks دون الحاجة لإدراج [tasks] في مصفوفة الاعتماديات؟

باستخدام دالة التحديث الوظيفية setTasks(prev => ...) التي تستلم أحدث حالة مباشرة من React.

06

يمكن الاعتماد على useMemo كقاعدة بيانات دائمة مضمونة بعدم إعادة الحساب إطلاقاً تحت أي ظرف.

خطأ؛ فخطاف useMemo مخصص لتحسين الأداء فقط وقد تعيد React حسابه عند تحرير الذاكرة أو التحديث السريع.

07

وفق إرشادات React الرسمية، ما الزمن التقريبي الذي يجعل العملية الحسابية النقية جديرة بالتخزين عبر useMemo؟

نحو 1 مللي ثانية فأكثر عند قياس زمن التنفيذ.

08

يُعد تغليف كل متغير وكل دالة في المشروع بـ useMemo وuseCallback أفضل ممارسة دائماً حتى بدون قياس.

خطأ؛ فالتذكر المفرط غير المبرر يعقد قراءة الكود ويضيف فحوصات اعتماديات بلا مكسب حقيقي.

09

ما الدور الذي يؤديه مترجم React Compiler الحديث في منظومة البناء؟

يحلل المكونات النقية وقت البناء ويطبق حفظ القيم والدوال وعناصر الواجهة تلقائياً.

10

أي تعبير مما يلي يكافئ وظيفياً استدعاء useCallback(fn, deps)؟

إرجاع تعريف الدالة نفسها من داخل useMemo بالصيغة useMemo(() => fn, deps).