مفهوم التأثيرات الجانبية (Side Effects) والتعرف على هوك useEffect
| المفهوم الهندسي | الآلية البرمجية في React | النتيجة |
|---|---|---|
| Side Effects | العمليات التي تتفاعل مع العالم الخارجي خارج نطاق رندرة JSX | جالب البيانات من API أو التعديل المباشر على عنوان الصفحة أو إنشاء مؤقتات زمنية |
| Lifecycle | المراحل الثلاث: التثبيت (Mounting) والتحديث (Updating) والإزالة (Unmounting) | تنفيذ العمليات البرمجية في الوقت المناسب بدقة دون تكرار عشوائي |
| Dependency Array | مصفوفة تحدد متى يُعاد تشغيل هوك useEffect بناءً على تغير متغيرات معينة | منع اللقات التكرارية اللانهائية (Infinite Loops) والتحكم التام في زمن التنفيذ |
| Cleanup Function | دالة يتم إرجاعها داخل useEffect لتنظيف الموارد قبل إزالة المكون | منع تسريب الذاكرة (Memory Leaks) وإيقاف المؤقتات والانشتراكات المفتوحة |
وظيفة مكون ريأكت الأساسية هي أخذ البيانات (Props & State) وتحويلها إلى وسوم واجهة (JSX). هذه العملية يجب أن تكون نقية (Pure) وخالية من المفاجآت.
ولكن، في التطبيقات الحقيقية نحتاج للقيام بعمليات تخرج عن نطاق رسم الواجهة:
كل هذه العمليات تُسمى هندسياً تأثيرات جانبية (Side Effects)، والمكان المخصص والآمن لتنفيذها داخل المكونات الوظيفية هو الهوك الشهير useEffect.
يقوم useEffect بتأجيل تنفيذ الكود المكتوب داخله إلى ما بعد انتهاء رندرة الواجهة ورسمها على الشاشة (After Render) لضمان عدم تعطيل استجابة الصفحة للمستخدم. يتكون الهوك من جزءين رئيسيين:
| 1 | useEffect(() => { |
| 2 | // 1. الكود المراد تنفيذه (Side Effect) |
| 3 | |
| 4 | return () => { |
| 5 | // 2. دالة التنظيف (Cleanup Function) - اختيارية |
| 6 | }; |
| 7 | }, [/* 3. مصفوفة التبعيات (Dependency Array) */]); |
تتحكم مصفوفة التبعيات (المعامل الثاني) في توقيت وتكرار تشغيل useEffect:
| 1 | // خطر: يُنفذ بعد كل رندرة للمكون بلا استثناء |
| 2 | useEffect(() => { |
| 3 | console.log('تم إعادة رسم المكون!'); |
| 4 | }); |
تُستخدم لجلب البيانات أو إعداد المكون عند ظهوره لأول مرة على الشاشة.
| 1 | // يُنفذ مرة واحدة فقط عندما يظهر المكون في الشاشة |
| 2 | useEffect(() => { |
| 3 | document.title = "مرحباً بك في منصة نوفيل"; |
| 4 | }, []); |
| 1 | // يُنفذ فقط عندما تتغير قيمة courseId |
| 2 | useEffect(() => { |
| 3 | fetchCourseDetails(courseId); |
| 4 | }, [courseId]); |
عندما ينشئ التأثير الجانبي اشتراكاً حياً (مثل مؤقت زمني أو اتصال عبر WebSockets)، يجب إغلاقه قبل إزالة المكون من الشاشة (Unmount) لمنع استهلاك الذاكرة (Memory Leak).
| 1 | useEffect(() => { |
| 2 | const timer = setInterval(() => { |
| 3 | console.log('تنبيه دوري...'); |
| 4 | }, 1000); |
| 5 | |
| 6 | // دالة التنظيف: تُنفذ تلقائياً عند مسح المكون من الشاشة |
| 7 | return () => clearInterval(timer); |
| 8 | }, []); |
إذا قمت بتحديث حالة (setState) داخل useEffect بدون تحديد مصفوفة التبعيات:
| 1 | // كود يسبب انهيار المتصفح فوراً! |
| 2 | useEffect(() => { |
| 3 | setCount(count + 1); // تحديث الحالة يطلق رندرة جديدة -> الرندرة تطلق useEffect -> وهكذا للأبد! |
| 4 | }); |