في هذا الدرس 6تصفّح المواضيع
كثيراً ما يحتاج مكونان شقيقان إلى تنسيق حالتهما معاً؛ كقائمة أكورديون يتطلب فتح أحد ألواحها إغلاق اللوح الآخر تلقائياً، أو حقلي تحويل وحدات متزامنين. وطالما احتفظ كل مكون فرعي بمتغير useState() محلي معزول داخله، فلن يملك أي شقيق وسيلة لإبلاغ شقيقه بالتغيير.
في نموذج تدفق البيانات أحادي الاتجاه في React لا تعدل المكونات الشقيقة بعضها مباشرة، بل تتنسق عبر المكون الأب المشترك بينها.
function SyncedLengths() {
const [m, setM] = useState(2);
return (
<div>
<UnitField unit="m" value={m} onChange={setM} />
<UnitField unit="cm" value={m * 100}
onChange={(cm) => setM(cm / 100)} />
</div>
);
}
يُنفّذ رفع الحالة للأعلى (Lifting State Up) في ثلاث خطوات هندسية واضحة:
- إزالة متغير
useState()المحلي من المكونات الأبناء. - تمرير القيمة المشتركة نزولاً من أقرب أب مشترك عبر الخصائص مثل
isActive={activeIndex === 0}. - تمرير دالة معالجة حدث نزولاً مثل
onShow={() => setActiveIndex(0)}ليطلب الابن من أبيه تحديث الحالة عند التفاعل.
function Accordion() {
const [activeIdx, setActiveIdx] = useState(0);
return (
<>
<Panel title="Overview" isActive={activeIdx === 0}
onShow={() => setActiveIdx(0)} />
<Panel title="Syllabus" isActive={activeIdx === 1}
onShow={() => setActiveIdx(1)} />
</>
);
}
يمتد مصطلحا ذاتي الإدارة (Uncontrolled) والموجَّه بالخصائص (Controlled) في معمارية React ليشملا مكوناتك المخصصة كلها وليس عناصر النماذج فحسب:
- المكون ذاتي الإدارة: يحتفظ بحالته داخلياً عبر
useState()، فيسهل تركيبه بأقل إعدادات لكن يصعب تنسيقه خارجياً. - المكون الموجَّه بالخصائص: يستقبل حالته ودوال تغييره من أبيه عبر Props، مما يمنح الأب تحكماً كاملاً في تنسيقه مع أشقائه.
كيف تميز React أي حالة تخص أي مكون عبر عمليات إعادة التصيير؟ تربط المكتبة كل حالة بموضع المكون داخل شجرة العرض وليس بسطر JSX المكتوب في الملف!
فإذا بدل شرط ثلاثي بين <ScoreCounter isFancy={true} /> و<ScoreCounter isFancy={false} /> في نفس الموضع الأول تماماً، ترى React أنه نفس نوع المكون في نفس الخانة الشجرية فتحافظ على قيمة عداده دون مسح.
function Arena() {
const [highlight, setHighlight] = useState(false);
return (
<div>
{highlight ? <Counter accent /> : <Counter />}
<button onClick={() => setHighlight(!highlight)}>
Toggle Style
</button>
</div>
);
}
في المقابل، تحذف React حالة المكون بالكامل فور إزالته من الشجرة بـ false أو استبدال نوع العنصر في ذلك الموضع بنوع مختلف، كاستبدال الغلاف <div> بوسم <section>.
ولهذا السبب تحديداً، إياك وتعريف دالة مكون فرعي داخل جسم دالة مكون أب؛ لأن ذلك ينشئ مرجع دالة جديداً في كل تصيير فتظنه React مكوناً مختلفاً وتمسح حالته وتركيز المؤشر مع كل ضغطة مفتاح!
أحياناً يشغل المكون نفس الموضع والنوع في الشجرة لكنه يمثل كياناً مختلفاً منطقياً، مثل صندوق كتابة محادثة <ChatComposer /> عند التبديل من مراسلة «سارة» إلى «عمر». افتراضياً تحتفظ React بنص المسودة المكتوب مما قد يوقع المستخدم في خطأ إرسال الرسالة للشخص الخطأ!
مرر خاصية key={selectedUser.id} لإبلاغ React بأن صندوق كل مستلم يمثل هوية مستقلة؛ فبمجرد تغير المفتاح تحذف المكتبة النسخة السابقة وتنشئ نسخة نظيفة بحالة ابتدائية فارغة:
| سيناريو شجرة الواجهة | سلوك المطابقة في React | مصير حالة المكون |
|---|---|---|
| نفس نوع المكون في نفس الموضع | تحديث خصائص النسخة القائمة نفسها | تبقى الحالة محفوظة كما هي |
| تغير نوع العنصر أو إزالته | إزالة الفرع القديم وبناء فرع جديد | تُمسح الحالة القديمة بالكامل |
| تغير قيمة خاصية المفتاح key | التعامل معه كهوية مكون جديدة مستقلة | تصفير الحالة تلقائياً للقيم الابتدائية |
| رفع الحالة للأب المشترك الأقرب | تمرير القيمة ودالة التحديث عبر الخصائص | تزامن تام ولحظي بين المكونات الشقيقة |
function Messenger() {
const [to, setTo] = useState(CONTACTS[0]);
return (
<div>
<ContactList list={CONTACTS} onSelect={setTo} />
<ChatBox key={to.id} contact={to} />
</div>
);
}
ملخص الدرس
حصاد الدرسمراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي
ماذا تعلّمت في هذا الدرس؟
تعلمت في هذا الدرس مزامنة المكونات الشقيقة برفع الحالة المشتركة إلى الأب الأقرب، والتمييز بين المكونات الموجهة وذاتية الإدارة، وفهم ارتباط عمر الحالة بموضع الشجرة وكيفية تصفيرها عمداً بتمرير خاصية المفتاح key. الخطوة التالية: انتقل الآن إلى الدرس رقم 27 «منهجية التفكير بطريقة React خطوة بخطوة» لمواصلة البناء التراكمي المتدرج في مسار React الحديث.
سجّل الدخول لحفظ تقدمك
تابع إنجاز المواضيع والمصطلحات والمهام، وكمّل من آخر خطوة على أي جهاز.
المصطلحات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 Lifting State Up رفع الحالة للأعلى
- نقل الحالة من المكونات الفرعية إلى أقرب أب مشترك بينها لتتشارك جميعاً مصدراً واحداً للحقيقة.
- للمراجعة
- 02 Closest Common Parent الأب المشترك الأقرب
- أقرب مكون حاضن في الشجرة يعلو كافة المكونات الفرعية المحتاجة لقراءة أو تعديل الحالة المشتركة.
- للمراجعة
- 03 UI Tree Position الموضع في شجرة العرض
- الموقع البنيوي الذي يشغله المكون داخل شجرة الواجهة وترتبط به ذاكرة خطافاته عبر التصييرات.
- للمراجعة
- 04 Key-Based Reset التصفير عبر المفتاح key
- تمرير خاصية key متغيرة لإجبار React على إزالة حالة النسخة القديمة وإنشاء حالة نظيفة جديدة.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
الاختصارات4
راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.
- 01 API API
- Application Programming Interface
- عقد الخصائص ودوال الأحداث الذي يقدمه المكون الفرعي لأبيه للتحكم في سلوكه.
- للمراجعة
- 02 UI UI
- User Interface
- شجرة المكونات التي تبنيها React من JSX لتتبع هوية العناصر وحفظ حالتها.
- للمراجعة
- 03 USD USD
- United States Dollar
- مثال شائع في محولات العملات ثنائية الحقل التي تعتمد على رفع الحالة إلى الأب المشترك.
- للمراجعة
- 04 JSX JSX
- JavaScript XML
- الصياغة التصريحية التي تحدد شجرة العناصر المعادة منها مواضع المكونات أثناء المطابقة.
- للمراجعة
لا توجد بطاقات تطابق البحث والتصفية.
اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.
مهامك قبل الاختبار
خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.
-
افتح مثال CourseAccordion وأضف لوحاً ثالثاً مربوطاً بالفهرس 2 وتأكد من إغلاق اللوحين الآخرين فور فتحه.
-
افتح مثال Messenger واكتب مسودة لسارة ثم انتقل لعمر لملاحظة تصفير النص بفضل خاصية key وجرب حذفها لرؤية الفارق.
تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.
اختبر فهمك.
ووصلها للإتقان.
كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.
أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.
الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.
لمحة عن التحدي10 أسئلة تنتظرك +
عندما يحتاج مكونان شقيقان إلى بقاء واجهتهما متزامنة دائماً، أين ينبغي أن توضع حالتهما المشتركة؟
تُرفع الحالة إلى أقرب مكون أب مشترك بينهما وتُمرر القيمة ودالة التحديث نزولاً عبر الخصائص.
كيف يبلغ المكون الابن الموجَّه أباه المشترك برغبة المستخدم في توسيعه عند النقر؟
باستدعاء دالة رد النداء الممررة إليه كخاصية من الأب مثل onShow.
عند تبديل الشرط بين نسختين من نفس المكون Counter في نفس الموضع تماماً تحتفظ React بحالة العداد دون تصفير.
صواب؛ لأن نفس نوع المكون لا يزال يشغل الخانة نفسها في شجرة العرض.
لماذا يُحظر تعريف دالة مكون فرعي داخل جسم دالة مكون أب في React؟
لأن كل تصيير للأب ينشئ دالة بمؤشر جديد فتعتبره React مكوناً مختلفاً وتمسح حالته وتركيزه في كل مرة.
كيف تخبر React بتصفير جميع الحالات الداخلية لمكون المحادثة ChatBox تلقائياً فور تغير معرّف المستلم؟
بتمرير خاصية key={active.id} للمكون فتنشئ React نسخة جديدة نظيفة لكل مستلم.
يقتصر عمل خاصية key في React على حلقات تكرار المصفوفات فقط ولا أثر لها على المكونات المنفردة.
خطأ؛ تعمل خاصية key مع أي مكون لتحديد هويته وتصفير حالته متى تغيرت قيمة المفتاح.
في مصطلحات هندسة المكونات، ماذا يُسمى المكون المخصص الذي تُدار حالته بالكامل عبر خصائص يمررها المكون الأب؟
يُسمى مكوناً موجَّهاً أو محكوماً بالخصائص Controlled Component.
عندما تتغير قيمة الشرط من صواب إلى خطأ ويُزال المكون من شجرة العرض، تحذف React حالته الداخلية تلقائياً.
صواب؛ إزالة المكون من شجرة الواجهة تنهي دورة حياته وتمسح حالته المحلية.
ماذا يحدث لحالة العداد الداخلي إذا تغير العنصر الحاضن له في الموضع نفسه من div إلى article؟
تغير نوع العنصر الأب من div إلى article يهدم الشجرة الفرعية القديمة وينشئ شجرة جديدة فتتصفر حالة العداد.
إذا عرضت مكونين <Counter /> متجاورين جنباً إلى جنب داخل نفس الحاوية، فكيف تتصرف حالتاهما؟
يشغل كل منهما موضعاً مستقلاً في الشجرة فيحتفظ كل عداد بحالته المنفصلة تماماً.