في هذا الدرس 6تصفّح المواضيع
صُمم خطاف useEffect كمنفذ لمزامنة الأنظمة الخارجية حصراً؛ فإذا لم يكن هناك نظام خارجي حقيقي فإن إقحام التأثير يجعل الكود أبطأ وأصعب في التتبع وعرضة للوميض البصري. إذ يجبر التأثير الزائد مكتبة React على التصيير أولاً بقيمة قديمة، ورسمها على الشاشة، ثم تشغيل التأثير وإطلاق دورة تصيير ثانية مهدرة فوراً.
لذلك يُعد حذف التأثيرات غير الضرورية من أرفع مهارات تحسين جودة وأداء تطبيقات React الحديثة.
متى أمكن حساب قيمة بالكامل اعتماداً على props أو state الموجودة بالفعل — مثل دمج الاسم الكامل، أو تصفية قائمة الدورات، أو جمع إجمالي الساعات — فلا تضعها في حالة مستقلة ولا تحدثها عبر useEffect أبداً.
احسبها مباشرة كمتغير const عادي في جسم دالة المكون لتكون محدثة ودقيقة بنسبة 100% منذ دورة التصيير الأولى.
const [query, setQuery] = useState('');
const visible = COURSES.filter((c) =>
c.title.toLowerCase().includes(query.toLowerCase())
);
const totalHours = visible.reduce(
(sum, c) => sum + c.hours,
0
);
للحسم الدقيق بين وضع الكود في معالج الحدث أو داخل التأثير، اسأل نفسك لماذا يجب أن يعمل هذا السطر الآن:
- لأن المستخدم ضغط زراً محدداً أو أرسل نموذجاً: ضع الكود داخل
onClickأوonSubmitمباشرة؛ وإذا اشترك زرّان في نفس الخطوات فاستخرج دالة مساعدة عادية واستدعها منهما معاً بدلاً من رفع راية حالة مؤقتة لتشغيل تأثير! - لأن المكون ظهر وعُرض أمام المستخدم على الشاشة: هنا نستخدم
useEffect.
من أكثر الأخطاء شيوعاً كتابة useEffect(() => { setComment(""); }, [userId]) داخل مكون فرعي لتفريغ المسودة عند الانتقال لطالب أو ملف شخصي آخر؛ إذ يعرض ذلك مسودة المستخدم السابق للحظة فوق ملف المستخدم الجديد قبل مسحها!
الحل الهندسي الأنظف هو تمرير المعرّف لخاصية المفتاح <CommentDraft key={userId} user={activeUser} />؛ فتعاملها React كنسخة مكون جديدة وتصفّر حالتها الداخلية تلقائياً في تصيير واحد.
function Workspace() {
const [studentId, setStudentId] = useState('s1');
return (
<MentorNoteBox
key={studentId}
studentId={studentId}
/>
);
}
تجنب كذلك «سلاسل التأثيرات المتعاقبة» حين يحدّث المكون الفرعي حالته في حدث النقر ثم يعتمد على useEffect منفصل لإبلاغ المكون الأب عبر onChange(nextValue)؛ فذلك يبعثر التحديث الواحد على عدة تصييرات متتالية.
البديل السليم هو استدعاء دالة الأب وتحديث الحالة معاً داخل نفس دالة الحدث، أو رفع الحالة بالكامل للأب ليصبح المكون الفرعي محكوماً وبسيطاً.
اعتمد جدول القرار الهندسي التالي بوصلةً عملية لتحديد الموضع الصحيح لكل منطق برمجي داخل تطبيقات React:
| الهدف البرمجي | النمط الخاطئ بـ useEffect | الحل الهندسي الأنظف في React |
|---|---|---|
| تصفية القوائم أو حساب المجاميع | نسخ النتيجة في حالة ثانية داخل تأثير | حساب القيمة مباشرة بمتغير const أثناء العرض |
| تصفير حالة مكون فرعي عند تغير المعرّف | تصفير الحقول يدوياً داخل useEffect | تمرير خاصية key={id} للمكون الفرعي مباشرة |
| إرسال طلب أو إبلاغ الأب عند النقر | رفع راية حالة لتشغيل تأثير لاحق | تنفيذ الإجراء مباشرة داخل دالة الحدث onClick |
| مزامنة عنوان الصفحة أو مستمع النافذة | التعديل المباشر أثناء دالة التصيير | استخدام useEffect مع اعتماديات دقيقة وتنظيف |
ملخص الدرس
حصاد الدرسمراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي
ماذا تعلّمت في هذا الدرس؟
تعلّمت في هذا الدرس رصد وإزالة استدعاءات useEffect الزائدة عبر اشتقاق البيانات مباشرة أثناء التصيير، ومعالجة إجراءات المستخدم في دوال الأحداث، وتصفير حالة المكونات الفرعية فورياً بخاصية key، ودمج إبلاغ المكون الأب بكفاءة. الخطوة التالية: انتقل الآن إلى الدرس رقم 37 «جلب البيانات من واجهات API داخل مكونات React» لمواصلة البناء التراكمي المتدرج في مسار React الحديث.
سجّل الدخول لحفظ تقدمك
تابع إنجاز المواضيع والمصطلحات والمهام، وكمّل من آخر خطوة على أي جهاز.
المصطلحات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 Derived Value القيمة المشتقة
- كل قيمة تُحسب مباشرة أثناء التصيير من الخصائص والحالة الحالية دون تخزينها في حالة مكررة.
- للمراجعة
- 02 Redundant Effect التأثير الزائد
- استخدام غير ضروري لخطاف useEffect لتحويل بيانات داخلية أو معالجة نقرة مما يسبب تصييراً مضاعفاً.
- للمراجعة
- 03 Key Reset Pattern نمط التصفير بالمفتاح
- تمرير معرّف متغير لخاصية key لإزالة النسخة السابقة وتركيب نسخة جديدة بحالة ابتدائية نظيفة.
- للمراجعة
- 04 Effect Chain سلسلة التأثيرات المتعاقبة
- نمط سيئ يشغّل فيه كل تأثير تأثيراً آخر عبر تحديثات حالة متلاحقة بدلاً من الدمج في حدث واحد.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
الاختصارات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 UI UI
- User Interface
- واجهة المستخدم التي تبقى خالية من الوميض بفضل حساب البيانات المشتقة في دورة رسم واحدة.
- للمراجعة
- 02 ID ID
- Identifier
- معرّف السجل الفريد الذي نمرره لخاصية key لتصفير حالة المكون الفرعي عند التبديل.
- للمراجعة
- 03 JSX JSX
- JavaScript XML
- بنية العناصر في React حيث تتحكم سمة key في هوية المكون واستمرارية حالته.
- للمراجعة
- 04 DOM DOM
- Document Object Model
- شجرة المتصفح التي نوفر عليها التحديثات المزدوجة بحذف التأثيرات غير الضرورية.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
مهامك قبل الاختبار
خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.
-
افتح مثال DerivedCatalog وأضف مربع اختيار لتصفية الوحدات ذات 5 ساعات فأكثر مباشرة أثناء دالة التصيير.
-
اكتب ملاحظة للطالبة Noor في المثال ثم انتقل إلى Tariq وتأكد من تفريغ الحقل لحظياً بفضل خاصية المفتاح.
تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.
اختبر فهمك.
ووصلها للإتقان.
كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.
أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.
الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.
لمحة عن التحدي10 أسئلة تنتظرك +
عند وجود firstName وlastName في الحالة، ما الطريقة الهندسية الأنظف لعرض الاسم الكامل fullName؟
حساب الاسم الكامل مباشرة في متغير const داخل جسم دالة التصيير دون حالة إضافية أو تأثير.
تؤدي مزامنة القيم المشتقة عبر useEffect وحالة إضافية إلى دورة تصيير زائدة بعد رسم بيانات متأخرة.
صواب؛ إذ يرسم المتصفح القيمة القديمة أولاً ثم يعمل التأثير ليجبر المكون على إعادة التصيير مرة ثانية.
كيف نصفر جميع حالات المكون الفرعي <ProfileEditor /> تلقائياً فور تغير معرّف المستخدم selectedUser.id؟
نمرر خاصية key={selectedUser.id} لتستبدل React النسخة القديمة بأخرى جديدة ذات حالة ابتدائية نظيفة.
أين نضع كود تأكيد التسجيل وإظهار الإشعار المرتبط حصراً بنقر المستخدم على زر التسجيل؟
الإجراءات الناتجة عن فعل محدد من المستخدم مكانها الطبيعي داخل معالج الحدث onClick أو onSubmit.
تعمل خاصية key داخل قوائم map() فقط ولا تأثير لها عند وضعها على مكون فرعي منفرد.
خطأ؛ فتغيير قيمة key على أي مكون منفرد يأمر React باستبدال نسخته وتصفير حالته فوراً.
عندما يحتاج مكون تبديل إلى تحديث حالته وإبلاغ المكون الأب عبر onChange(next)، كيف نتفادى التأثير الزائد؟
نستدعي تحديث الحالة ودالة الأب معاً داخل نفس معالج الحدث ليدمجهما React في تصيير واحد.
إذا اشترك زرّان في نفس خطوات التحقق والتسجيل، كيف نمنع تكرار الكود دون اللجوء إلى useEffect؟
نستخرج دالة مساعدة عادية داخل المكون ونستدعيها مباشرة من كلا معالجي النقر.
إذا لم يكن هناك نظام خارجي وكنت تحسب بيانات الواجهة من الخصائص والحالة الحالية فقط، فلا حاجة غالباً إلى useEffect.
صواب؛ فالحساب المباشر والمفاتيح ومعالجات الأحداث تغطي تدفق البيانات الداخلي بكفاءة ونظافة.
أي حالة من الحالات الأربع التالية تتطلب فعلاً استخدام خطاف useEffect؟
ربط وإزالة مستمع حدث resize على كائن النافذة العام يمثل مزامنة حقيقية مع نظام خارجي.
تدمج مكتبة React 18 تلقائياً تحديثات الحالة المتعددة داخل نفس معالج النقر في دورة تصيير واحدة.
صواب؛ تحافظ ميزة الدمج التلقائي على سرعة واتساق الواجهة دون تصييرات متفرقة.