| الميزة التقنية | الآلية الهندسية في ريأكت | الفائدة المباشرة والتطبيق |
|---|---|---|
| props.children | استقبال كل ما يُكتب بين وسمي البداية والنهاية للمكون تلقائياً وحقنه في الواجهة | إتاحة الفرصة للمكون ليعمل كحاوية مرنة تستقبل وسوم HTML ومكونات أخرى بدون تحديد مسبق للبيانات |
| Layout Components | بناء الهياكل العامة الثابتة مثل الصناديق المنبثقة والنوافذ والإطارات الخارجية والبطاقات | توحيد التصميم والهوية البصرية للموقع بأكمله وكتابة أكواد التنسيق المشتركة لمرة واحدة فقط |
| Composition | دمج وحقن مكونات فرعية داخل مكونات حاوية بشكل شجري متداخل وعميق | بناء واجهات مستخدم معقدة جداً بأعلى درجة من المرونة والحرية البرمجية دون تضخيم حجم الملفات |
في الدرس السابق، تعلمنا كيف نمرر بيانات بسيطة (مثل النصوص والأرقام) إلى المكون عبر الـ Props، ونعرضها في أماكن محددة كالتالي: <CourseCard title="ريأكت"/>.
ولكن، تخيل أنك تبني صندوقاً منبثقاً (Modal) أو بطاقة عامة (Card Wrapper)، وتريد لهذا المكون أن يستقبل ويحتضن داخل جسده وسوماً كاملة، أو أزراراً مختلفة، أو حتى مكونات أخرى متكاملة لم تكن تعلم بشكل مسبق ما هي!
هنا تتدخل ريأكت لتمنحنا خاصية سحرية مدمجة تلقائياً في كائن الخصائص تُسمى props.children.
بشكل افتراضي، عندما تستدعي أي مكون في ريأكت، يمكنك كتابته بطريقتين:
أي شيء برمي تقوم بكتابته وزرعه بين وسم البداية ووسم النهاية للمكون (سواء كان نصاً عادياً، أو وسوم HTML مثل <h1> و <button>، أو مكونات ريأكت أخرى)، ستقوم ريأكت بجمعه تلقائياً وتغليفه ووضعه داخل خاصية مدمجة في كائن الـ props تحمل الاسم الصارم والمحجوز children.
تُستخدم هذه التقنية لبناء "مكونات التغليف" أو الهياكل العامة. بدلاً من إعادة كتابة أسطر تنسيقات الفريم الخارجي، أو الظلال، أو إطار النافذة في كل ملف، نقوم ببناء مكون حاوٍ واحد يتولى التنسيق الخارجي، ويفتح قلبه في المنتصف عبر استدعاء {children} ليتم عرض أي محتوى متغير يأتيه من الأب داخله.
دعنا نرى كيف ننشئ مكوناً حاوياً يمثل إطاراً لبطاقة أنيقة بظلال وخلفية خاصة، وكيف نستخدمه كحاوية مرنة لعدة محتويات مختلفة تماماً داخل المكون الأب (App):
CardWrapper.jsx
| 1 | // نقوم بتفكيك الخاصية السحرية children مباشرة من أقواس الدالة |
| 2 | function CardWrapper({ children }) { |
| 3 | const wrapperStyle = { |
| 4 | border: '1px solid #e0e0e0', |
| 5 | borderRadius: '12px', |
| 6 | padding: '25px', |
| 7 | boxShadow: '0 4px 15px rgba(0, 0, 0, 0.05)', |
| 8 | backgroundColor: '#ffffff', |
| 9 | maxWidth: '400px', |
| 10 | margin: '20px auto' |
| 11 | }; |
| 12 | |
| 13 | return ( |
| 14 | <div style={wrapperStyle}> |
| 15 | {/* ريأكت ستقوم بحقن كل ما يرسله الأب بين وسوم البداية والنهاية هنا تماماً */} |
| 16 | {children} |
| 17 | </div> |
| 18 | ); |
| 19 | } |
| 20 | |
| 21 | export default CardWrapper; |
App.jsx
| 1 | import CardWrapper from './CardWrapper'; |
| 2 | |
| 3 | function App() { |
| 4 | return ( |
| 5 | <div className="layout-container"> |
| 6 | <h2 style={{ textAlign: 'center' }}>تطبيقات تقنية props.children المرنة</h2> |
| 7 | |
| 8 | {/* الاستخدام الأول: تمرير نصوص وأزرار عادية داخل الحاوية */} |
| 9 | <CardWrapper> |
| 10 | <h3>إشعار منصة نوفيل</h3> |
| 11 | <p>تم تحديث سيرفرات الأكواد بنجاح فائق اليوم.</p> |
| 12 | <button style={{ backgroundColor: '#673ab7', color: '#fff', border: 'none', padding: '8px' }}>إغلاق</button> |
| 13 | </CardWrapper> |
| 14 | |
| 15 | {/* الاستخدام الثاني: تمرير محتوى مختلف تماماً (مثل صورة ونموذج إدخال) لنفس الحاوية */} |
| 16 | <CardWrapper> |
| 17 | <h3>تسجيل الدخول للمنصة</h3> |
| 18 | <input type="email" placeholder="اكتب بريدك الإلكتروني" style={{ display: 'block', margin: '10px 0', width: '100%' }} /> |
| 19 | <input type="password" placeholder="كلمة المرور" style={{ display: 'block', margin: '10px 0', width: '100%' }} /> |
| 20 | <button style={{ backgroundColor: '#4caf50', color: '#fff', border: 'none', padding: '8px 16px', width: '100%' }}>دخول</button> |
| 21 | </CardWrapper> |
| 22 | </div> |
| 23 | ); |
| 24 | } |
| 25 | |
| 26 | export default App; |
💡 نصيحة
تذكر دائماً أن الكلمة children هي كلمة محجوزة برمجياً داخل ريأكت وتُكتب بحروف صغيرة حتماً (children) لكي يتعرف عليها المحرك تلقائياً عند كتابة الوسوم الثنائية. التركاية الحقيقية هنا هي أنك تستطيع تمرير الـ children جنباً إلى جنب مع الـ props العادية الأخرى دون أي تعارض!
على سبيل المثال، يمكنك تصميم مكون حاوٍ يستقبل خاصية عادية لتحديد لون العنوان، وفي نفس الوقت يفتح قلبه لاستقبال الأبناء هكذا:
| 1 | function CustomBox({ titleColor, children }) { ... } |
| 2 |