0Pricing
Frontend Academy · درس

useMemo وuseCallback لتحسين الأداء

احفظ الحسابات المكلفة مؤقتًا باستخدام useMemo ومراجع الدوال الثابتة باستخدام useCallback لمنع إعادة تصيير المكوّنات الابنة دون حاجة.

useMemo وuseCallback لتحسين الأداء درس مجاني في Frontend Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Frontend Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Frontend Academy 4 دروس في المجموع.

سلوك React الافتراضي

يعيد React افتراضيًا تصيير المكوّن كلما تغيّرت حالته أو أُعيد تصيير المكوّن الأب. كما يُعاد تصيير المكوّنات الابنة حتى إذا لم تتغير خصائصها. وهذا مناسب لمعظم المكوّنات — فـ React سريع.

useMemo — تخزين القيم المكلفة مؤقتًا

تخزّن useMemo(fn, deps) نتيجة عملية حسابية مؤقتًا. ولا تُنفّذ الدالة إلا عند تغير التبعيات. استخدمها للحسابات المكلفة التي سيكون تكرارها في كل عملية تصيير هدرًا.

const expensiveResult = useMemo(() => {
  return items.filter(item => item.category === category).sort((a, b) => a.price - b.price);
}, [items, category]);
// Only recalculates when items or category changes

useCallback — تخزين الدوال مؤقتًا

تعيد useCallback(fn, deps) دالة مخزّنة مؤقتًا تحافظ على المرجع نفسه ما لم تتغير deps. استخدمها عند تمرير دوال الاستدعاء إلى مكوّنات متداخلة بعمق أو مكوّنات مُحسّنة.

const handleDelete = useCallback((id: string) => {
  setItems(prev => prev.filter(item => item.id !== id));
}, []); // stable reference — empty deps because only setItems is used

<ItemList items={items} onDelete={handleDelete} />

React.memo — تخطي إعادة التصيير

تغلّف React.memo(Component) مكوّنًا بحيث لا يُعاد تصييره إلا عند تغير خصائصه (بالمقارنة السطحية). ادمجها مع useCallback للحصول على خصائص دوال استدعاء ثابتة.

const MemoItem = React.memo(function Item({ text, onDelete }: ItemProps) {
  console.log('Item rendered:', text); // only logs when props change
  return <li>{text} <button onClick={onDelete}>×</button></li>;
});

// onDelete must be stable (from useCallback) for memo to help

متى لا تُحسّن الأداء

التحسين المبكر فخ. فـ useMemo وuseCallback لهما تكلفة: الدالة المغلقة ومقارنة deps. وبالنسبة إلى العمليات الرخيصة (مثل تصفية 10 عناصر)، تفوق التكلفة الفائدة. حسّن الأداء عندما تقيس مشكلة أداء حقيقية.

قياس الأداء قبل التحسين

استخدم React DevTools Profiler لقياس أزمنة التصيير الفعلية قبل إضافة التخزين المؤقت. يوضّح Profiler المكوّنات التي تستغرق أطول وقت وعدد مرات تصييرها. أصلح المشكلات استنادًا إلى الأدلة، لا إلى الافتراضات.

useMemo للمراجع الثابتة

يفيد useMemo أيضًا في إبقاء المرجع ثابتًا — ليس لتحسين أداء الحساب نفسه، بل لمنع memo أو effect لاحق من إعادة التشغيل دون داعٍ.

// Without useMemo, this creates a new array every render:
const config = useMemo(() => ({ endpoint: '/api', timeout: 5000 }), []);

// Without memoization, useEffect would re-run on every render:
useEffect(() => { initSDK(config); }, [config]);

تبعيات useCallback

يتبع useCallback قواعد التبعيات نفسها التي يتبعها useEffect. أدرج كل متغير من النطاق الخارجي تستخدمه دالة الاستدعاء. وتكون دوال تعيين الحالة (من useState) ثابتة دائمًا، ولا تحتاج إلى إدراجها في deps.

العلاقة بين useMemo وuseCallback

useCallback(fn, deps) مكافئة لـ useMemo(() => fn, deps). فهما الآلية نفسها — وuseCallback مجرد صيغة مختصرة لتخزين الدوال مؤقتًا تحديدًا.

التخزين المؤقت لعناصر القائمة

نمط شائع هو تخزين مكوّنات عناصر القائمة مؤقتًا عندما تكون القائمة كبيرة ويُعاد تصييرها كثيرًا. مرّر دوال استدعاء ثابتة من useCallback حتى لا تلغي فائدة التخزين المؤقت.

const MemoRow = React.memo(Row);
const handleEdit = useCallback((id) => edit(id), []);
const handleDel  = useCallback((id) => remove(id), []);

{rows.map(row => (
  <MemoRow key={row.id} row={row} onEdit={handleEdit} onDelete={handleDel} />
))}

تخزين قيمة Context مؤقتًا

خزّن القيمة الممررة إلى Context Provider مؤقتًا لمنع إعادة تصيير جميع المستهلكين كلما أُعيد تصيير المكوّن الأب لـ Provider.

const value = useMemo(() => ({ user, login, logout }), [user]);

تحقق سريع

ما الغرض من useCallback؟

مراجعة: useMemo وuseCallback

يخزّن useMemo القيم المحسوبة المكلفة مؤقتًا. ويخزّن useCallback مراجع الدوال مؤقتًا. يتخطى React.memo إعادة التصيير عندما لا تتغير الخصائص بالمقارنة السطحية. ادمج الثلاثة لتحسين أداء المكوّنات. قِس الأداء أولًا — فالتخزين المؤقت المبكر يضيف تعقيدًا دون فائدة. وتمنع المراجع الثابتة التأثيرات وعمليات التخزين المؤقت اللاحقة من إعادة التشغيل دون داعٍ.

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

هل درس «useMemo وuseCallback لتحسين الأداء» مجاني؟

نعم — نص درس «useMemo وuseCallback لتحسين الأداء» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Frontend Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Frontend Academy 4 دروس في المجموع.

ماذا ستتعلم في «useMemo وuseCallback لتحسين الأداء»؟

احفظ الحسابات المكلفة مؤقتًا باستخدام useMemo ومراجع الدوال الثابتة باستخدام useCallback لمنع إعادة تصيير المكوّنات الابنة دون حاجة. تتمرن على Frontend Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Frontend Academy؟

لا تُشترط خبرة سابقة. Frontend Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «useMemo وuseCallback لتحسين الأداء»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Frontend Academy هذا؟

نعم. كل درس في Frontend Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. useContext للحالة العامة
  2. useReducer للحالة المعقّدة
  3. useMemo وuseCallback لتحسين الأداء
  4. الخطافات المخصّصة: استخراج المنطق القابل لإعادة الاستخدام
← العودة إلى Frontend Academy