في هذا الدرس 6تصفّح المواضيع
كثير من عمليات المزامنة الخارجية مستمرة بطبيعتها وليست خطوة لحظية تنتهي فوراً؛ فتشغيل مؤقت دوري عبر setInterval أو تسجيل مستمع على النافذة عبر window.addEventListener أو فتح اشتراك بقناة بيانات يظل نشطاً في ذاكرة المتصفح إلى أن نوقفه صراحةً.
إذا أخفى المستخدم المكون أو انتقل لشاشة أخرى دون إلغاء ما بدأه التأثير، ستتراكم المؤقتات اليتيمة وتتضاعف المستمعات مع كل زيارة مما يسبب تسرب الذاكرة وتضارب تحديثات الواجهة.
لإيقاف أي تأثير مستمر بنظافة، أعِد دالة تنظيف (Cleanup Function) من نهاية دالة useEffect بالشكل return () => { ... }. تستدعي React دالة التنظيف هذه تلقائياً في موضعين دقيقين:
- قبل إعادة تشغيل التأثير: عند تغير إحدى الاعتماديات تنفذ React تنظيف الدورة السابقة بقيمها القديمة أولاً قبل بدء الإعداد الجديد.
- عند إزالة المكون (Unmount): مرة أخيرة فور اختفاء المكون من شجرة الواجهة.
useEffect(() => {
onLog('+ Connected to #' + room);
return () => {
onLog('- Disconnected from #' + room);
};
}, [room]);
كلما أنشأ التأثير مؤقتاً عبر setInterval() أو setTimeout()، احفظ معرّف المؤقت في ثابت محلي داخل دالة التأثير ثم ألغِه فوراً في دالة التنظيف باستدعاء clearInterval(id) أو clearTimeout(id).
ادمج ذلك مع دالة التحديث المعتمدة على القيمة السابقة setSeconds((s) => s + 1) ليعمل العداد بسلاسة دون الحاجة لإعادة إنشاء المؤقت في كل ثانية.
useEffect(() => {
if (!active) return;
const id = setInterval(() => {
setSeconds((s) => s + 1);
}, 1000);
return () => clearInterval(id);
}, [active]);
ترتبط خصائص مثل onClick بعناصر المكون نفسه، أما الأحداث العامة على مستوى المتصفح — كتغير عرض النافذة resize أو حالة الاتصال بالشبكة أو اختصارات لوحة المفاتيح العامة مثل مفتاح Escape — فتُسجل على كائن window أو document.
عرّف دالة معالجة مسماة داخل التأثير، ومررها إلى window.addEventListener، ثم مرر نفس مرجع الدالة بالضبط إلى window.removeEventListener داخل دالة التنظيف.
useEffect(() => {
function onKey(e) {
setLastKey(e.key);
}
window.addEventListener('keydown', onKey);
return () => {
window.removeEventListener('keydown', onKey);
};
}, []);
في معمارية React الدالية الحديثة، تخلَّ عن التفكير بطريقة مراحل الأصناف المتفرقة القديمة، وفكّر في كل تأثير كزوج متناظر مستقل من بدء المزامنة وإيقاف المزامنة. اجعل كل استدعاء useEffect مسؤولاً عن مهمة مترابطة واحدة؛ فإذا أردت مزامنة عنوان الصفحة ومراقبة عرض النافذة معاً، افصلهما في خطافين مستقلين واضحين.
في طور التطوير، يتعمد غلاف <StrictMode> تشغيل دورة اختبار إضافية بالترتيب إعداد ← تنظيف ← إعداد فور تركيب المكون. فإذا لاحظت تضاعف سرعة العداد في وضع التطوير، لا تحذف الوضع الصارم، بل أصلح دالة التنظيف المفقودة التي كشفها لك مبكراً قبل وصول الكود للإنتاج! يوضح الجدول الآتي أزواج التنظيف القياسية:
| عملية الإعداد في التأثير | دالة التنظيف المتناظرة | نتيجة إهمال دالة التنظيف |
|---|---|---|
| تشغيل مؤقت دوري setInterval | إلغاء المؤقت عبر clearInterval(id) | تراكم مؤقتات مزدوجة وتضاعف سرعة العداد |
| جدولة تأخير زمني setTimeout | إلغاء الجدولة عبر clearTimeout(id) | تنفيذ متأخر غير مرغوب بعد مغادرة الشاشة |
| تسجيل مستمع window.addEventListener | إزالة المستمع عبر removeEventListener | تسرب ذاكرة وتكرار تنفيذ الحدث عشرات المرات |
| فتح اتصال أو أداة خارجية connect | إغلاق الاتصال عبر disconnect أو close | بقاء قنوات يتيمة مفتوحة وتداخل بيانات الغرف |
ملخص الدرس
حصاد الدرسمراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي
ماذا تعلّمت في هذا الدرس؟
أتقنت في هذا الدرس كتابة دوال التنظيف في useEffect، وتتبعت ترتيب الإعداد والهدم عند تغير الاعتماديات وإزالة المكون، وألغيت المؤقتات ومستمعي النافذة بأمان مع استيعاب عقلية بدء وإيقاف المزامنة وفحص StrictMode. الخطوة التالية: انتقل الآن إلى الدرس رقم 36 «متى لا تحتاج إلى useEffect والبدائل الهندسية الأنظف» لمواصلة البناء التراكمي المتدرج في مسار React الحديث.
سجّل الدخول لحفظ تقدمك
تابع إنجاز المواضيع والمصطلحات والمهام، وكمّل من آخر خطوة على أي جهاز.
المصطلحات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 Cleanup Function دالة التنظيف
- دالة تُعاد من داخل useEffect وتتولى إلغاء المؤقتات والمستمعات والاشتراكات التي أنشأها الإعداد.
- للمراجعة
- 02 Memory Leak تسرب الذاكرة
- بقاء مؤقتات أو مستمعات نشطة تستهلك الذاكرة والمعالج بعد إزالة المكون من الواجهة.
- للمراجعة
- 03 Synchronization Pair زوج المزامنة المتناظر
- تصميم كل إجراء فتح أو اشتراك في التأثير مقروناً بإجراء الإغلاق المعاكس له تماماً.
- للمراجعة
- 04 Unmount إزالة المكون
- لحظة حذف نسخة المكون من شجرة العرض واستدعاء دوال تنظيف تأثيراته للمرة الأخيرة.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
الاختصارات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 CPU CPU
- Central Processing Unit
- موارد المعالج التي تُستنزف عند ترك مؤقتات خلفية منسية تعمل بلا توقف.
- للمراجعة
- 02 RAM RAM
- Random Access Memory
- ذاكرة المتصفح التي تبقى محجوزة بسبب عدم إزالة مستمعات الأحداث العامة.
- للمراجعة
- 03 DOM DOM
- Document Object Model
- أهداف النافذة والمستند العامة التي نربط بها مستمعات لوحة المفاتيح وتغير الحجم.
- للمراجعة
- 04 UI UI
- User Interface
- عروض المكونات التفاعلية التي تُركب وتُزال ديناميكياً أثناء تنقل المستخدم.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
مهامك قبل الاختبار
خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.
-
افتح مثال LifecycleInspector وبدّل من غرفة general إلى hooks وتحقق من ظهور سطر التنظيف قبل سطر الاتصال الجديد.
-
عدّل دالة handleKeyDown بحيث يؤدي الضغط على مفتاح Escape إلى عرض رسالة مسح مخصصة مع الحفاظ على التنظيف السليم.
تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.
اختبر فهمك.
ووصلها للإتقان.
كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.
أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.
الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.
لمحة عن التحدي10 أسئلة تنتظرك +
كيف نعرّف آلية التنظيف داخل خطاف useEffect في React؟
نعيد دالة تنظيف سهمية أو مسماة من نهاية دالة الإعداد داخل useEffect.
في أي الأوقات تستدعي مكتبة React دالة التنظيف المعادة من التأثير؟
تستدعيها React قبل إعادة تشغيل التأثير عند تغير الاعتماديات، وكذلك عند إزالة المكون من الشجرة.
يتعمد غلاف StrictMode في طور التطوير تشغيل دورة إعداد ثم تنظيف ثم إعداد إضافية لكشف أخطاء التنظيف مبكراً.
صواب؛ فإذا كانت دالة التنظيف متناظرة وسليمة فسيعمل المكون بكفاءة مطابقة للإنتاج تماماً.
لماذا يفشل تمرير دالة سهمية مجهولة جديدة إلى window.removeEventListener في إزالة المستمع السابق؟
لأن كل دالة سهمية مكتوبة مباشرة تنشئ مرجعاً جديداً مختلفاً في الذاكرة فلا يتطابق مع الدالة المسجلة.
ما السطر المتناظر الواجب إرجاعه لتنظيف المؤقت const id = setInterval(tick, 1000)؟
إرجاع دالة تنظيف تستدعي clearInterval(id) لإلغاء المؤقت بدقة.
عند تغير roomId من "general" إلى "hooks"، تقرأ دالة التنظيف الخاصة بالدورة السابقة القيمة القديمة "general" وتغلقها بدقة.
صواب؛ لأن دالة التنظيف تحتفظ بلقطة القيم التي أُنشئت معها في دورتها الخاصة.
إذا احتاج مكون إلى مزامنة عنوان الصفحة مع [unread] والاتصال بغرفة محادثة مع [roomId]، فما الهيكلة الأفضل؟
فصلهما في استدعاءين مستقلين لخطاف useEffect حتى لا ينقطع اتصال الغرفة عند تغير عداد الرسائل.
التأثير البسيط الذي يحدّث نص document.title فقط دون فتح مؤقت أو مستمع أو اشتراك لا يلزمه إرجاع دالة تنظيف.
صواب؛ نحتاج دالة التنظيف عندما يفتح التأثير عملية مستمرة أو مستمعاً أو اتصالاً يجب إيقافه.
أثناء التطوير داخل <StrictMode> لاحظت أن العداد يزيد بمقدار 2 في كل ثانية؛ ما الحل الهندسي الصحيح؟
إضافة دالة التنظيف clearInterval(timerId) لإلغاء المؤقت الأول بدلاً من إخفاء المشكلة بحذف StrictMode.
استخدام التحديث الدالي setSeconds(prev => prev + 1) داخل المؤقت يغني عن وضع متغير seconds في مصفوفة الاعتماديات.
صواب؛ إذ تستلم دالة التحديث أحدث قيمة تلقائياً دون الحاجة لهدم المؤقت وإعادة إنشائه كل ثانية.