0Pricing
React Academy · درس

حالات التنافس وتنظيف Effect

استخدم AbortController داخل useEffect لإلغاء طلبات fetch القديمة عند إعادة التصيير.

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

مرحبًا

في هذا الدرس ستتعلمون كيفية حدوث race conditions في تأثيرات React التي تجلب البيانات، وكيفية التخلص منها باستخدام AbortController لإجراء التنظيف.

ما هي race condition؟

تحدث race condition عندما تكتمل عمليتان غير متزامنتين بترتيب غير متوقع. في React، إذا تنقّل المستخدم بسرعة بين العناصر، فقد يكتمل fetch البطيء للعنصر A بعد fetch الخاص بالعنصر B، مما يؤدي إلى عرض بيانات قديمة.

الخلل: استجابة fetch قديمة

من دون التنظيف، إذا أعاد المكوّن التصيير بمعرّف جديد قبل اكتمال fetch القديم، فسيعمل الطلبان معًا. وقد تستبدل عملية fetch الأقدم والأبطأ البيانات الأحدث في الحالة.
useEffect(() => {
  fetch('/api/item/' + id)
    .then(r => r.json())
    .then(data => setData(data)); // may run AFTER a newer fetch!
}, [id]);

الإصلاح 1: علامة التجاهل

حل بسيط: اضبطوا علامة منطقية باسم `ignore` داخل التأثير. تضبطها دالة التنظيف على true. ويفحص callback الخاص بـ fetch العلامة قبل استدعاء setState.
useEffect(() => {
  let ignore = false;
  fetch('/api/item/' + id)
    .then(r => r.json())
    .then(data => { if (!ignore) setData(data); });
  return () => { ignore = true; };
}, [id]);

الإصلاح 2: AbortController

يُعد AbortController المعيار الحديث. أنشئوا controller داخل التأثير، ومرّروا signal الخاص به إلى fetch، ثم أوقفوه داخل دالة التنظيف. يُطلق fetch خطأً من نوع AbortError يمكنكم تجاهله.
useEffect(() => {
  const controller = new AbortController();
  fetch('/api/item/' + id, { signal: controller.signal })
    .then(r => r.json())
    .then(data => setData(data))
    .catch(err => {
      if (err.name === 'AbortError') return; // expected
      setError(err.message);
    });
  return () => controller.abort();
}, [id]);

AbortController مع async/await

استخدموا try/catch مع الدوال غير المتزامنة داخل useEffect. تجاهلوا AbortError داخل كتلة catch.
useEffect(() => {
  const ctrl = new AbortController();
  async function load() {
    try {
      const res = await fetch('/api/' + id, { signal: ctrl.signal });
      const json = await res.json();
      setData(json);
    } catch (e) {
      if (e.name !== 'AbortError') setError(e.message);
    }
  }
  load();
  return () => ctrl.abort();
}, [id]);

التنظيف مطلوب دائمًا

حتى عندما تكون احتمالية race conditions منخفضة، مثل fetch يُنفّذ مرة واحدة عند التحميل، أضيفوا التنظيف دائمًا. في React 18 StrictMode تُنفّذ التأثيرات مرتين؛ ومن دون التنظيف، يلوّث الطلب الأول المتروك الحالة.

المشكلة الخفية في async داخل useEffect

لا يمكن أن يكون callback الخاص بـ useEffect هو `async`. عرّفوا دالة غير متزامنة داخل التأثير واستدعُوها فورًا، أو استخدموا دالة عادية مع .then()/.catch().
useEffect(() => {
  // useEffect callback is NOT async
  async function fetchData() { /* ... */ }
  fetchData(); // call it
  return () => ctrl.abort();
}, [id]);

المكتبات تتولى ذلك عنكم

تتعامل React Query وSWR وRTK Query تلقائيًا مع race conditions والإيقاف والتنظيف. عند استخدام هذه المكتبات، لن تحتاجوا إلى كتابة شيفرة AbortController يدويًا.

اختبار race conditions

لاختبار race conditions يدويًا: افتحوا Network DevTools، واضبطوا سرعة الشبكة على «Slow 3G»، ثم انقروا بسرعة بين العناصر. من دون التنظيف، سترون بيانات قديمة تظهر للحظات. ومع AbortController، سيظهر العنصر المحدد أخيرًا فقط.

تحقق سريع

ماذا يفعل استدعاء controller.abort() داخل دالة تنظيف useEffect؟

مراجعة

تحدث race conditions عندما تحدّث استجابة fetch قديمة الحالة بعد وصول fetch أحدث. أصلحوا ذلك باستخدام علامة تجاهل أو AbortController. أوقفوا الطلب أو تجاهلوه دائمًا داخل تنظيف useEffect. تتولى مكتبات مثل React Query ذلك تلقائيًا.

التالي

الدرس التالي: **useTransition لتحديثات واجهة المستخدم غير الحاجبة** — ستغلّفون تحديثات الحالة المكلفة داخل startTransition للحفاظ على استجابة واجهة المستخدم.

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

هل درس «حالات التنافس وتنظيف Effect» مجاني؟

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

ماذا ستتعلم في «حالات التنافس وتنظيف Effect»؟

استخدم AbortController داخل useEffect لإلغاء طلبات fetch القديمة عند إعادة التصيير. تتمرن على React Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

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

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

كم من الوقت يستغرق درس «حالات التنافس وتنظيف Effect»؟

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

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

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

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

  1. حالات التنافس وتنظيف Effect
  2. استخدام useTransition لتحديثات واجهة غير حاجبة
  3. استخدام useDeferredValue لتأخير إدخال المستخدم
  4. استخدام Suspense لحدود البيانات والتعليمات البرمجية
← العودة إلى React Academy