Menu
flag Ar iconالعربيةdown icon

الـ prop المسماة children في React: المغلّفات والخانات

children هي الـ prop التي تحمل كل ما تضعه بين وسمي فتح المكوّن وإغلاقه. تعلّم كيف تبني بها مكوّنات مغلّفة ومكوّنات تخطيط، وتمرر عدة خانات كـ props مسماة، وتستخدم children كدالة، ومتى تكون واجهة Children الأداة الخاطئة.

تحتوي هذه الصفحة على محررات قابلة للتشغيل - حرّر، شغّل، وشاهد النتيجة فوراً.

في React، children هي الـ prop التي تحمل كل ما تكتبه بين وسمي فتح المكوّن وإغلاقه. المكوّن الذي يعرض {children} في موضع ما من مخرجاته يصبح مغلّفًا: هو يوفر الإطار، والمستدعي يوفر المحتوى.

تتشارك البطاقتان حدًا واحدًا وحشوة واحدة ونمط عنوان واحدًا، لكن كل واحدة تحمل محتوى مختلفًا تمامًا. أضف <Card title="Help"> ثالثة بداخلها رابط فتحصل على الإطار نفسه مجانًا.

كيف تصل children إلى المكوّن

تحوّل JSX المحتوى المتداخل إلى prop. هذان السطران ينتجان العنصر نفسه:

<Card title="Profile"><p>Ada</p></Card>

<Card title="Profile" children={<p>Ada</p>} />

إذن children prop عادية لها طريقة خاصة في التمرير. تفككها مثل أي prop أخرى (function Card({ children })) أو تقرؤها على أنها props.children. تتناول صفحة props الـ props عمومًا.

ما يصل في children يعتمد على ما كتبته بين الوسمين. الابن الواحد يصل كما هو. والأبناء المتعددون يصلون كمصفوفة. والنص يصل كسلسلة نصية، ولا شيء على الإطلاق يصل على أنه undefined.

تُظهر وحدة التحكم object وarray of 2 وstring وundefined. نادرًا ما تحتاج إلى الاهتمام بذلك: عرض {children} يتعامل مع كل هذه الحالات، والقيم null وundefined وtrue وfalse لا تعرض شيئًا. لا يهم الشكل إلا إذا حاولت فحص الأبناء أو تغييرهم، وهو ما يحذّر منه القسم الأخير.

مكوّنات التخطيط

أشيع استخدام لـ children هو مكوّن التخطيط: هيكل صفحة، أو تخطيط بشريط جانبي، أو عمود في المنتصف. يملك المكوّن البنية والمسافات، وكل صفحة تستخدمه تمرر محتواها الخاص.

function PageLayout({ children }) {
    return (
        <div className="page">
            <Header />
            <main className="page-content">{children}</main>
            <Footer />
        </div>
    );
}

function AboutPage() {
    return (
        <PageLayout>
            <h1>About us</h1>
            <p>We teach people to code.</p>
        </PageLayout>
    );
}

لا يعرف PageLayout ولا يهتم بما تحتويه صفحة «من نحن». وهذا الفصل هو المقصود: غيّر الترويسة مرة واحدة فتلتقطها كل صفحة مغلّفة بالتخطيط.

عدة خانات عبر props مسماة

children خانة واحدة. عندما يحتاج مكوّن إلى محتوى في أكثر من موضع، مرّر القطع الإضافية كـ props مسماة. يمكن لأي prop أن تحمل JSX، فتستطيع النافذة المنبثقة أن تأخذ title وfooter وجسمها على أنه children.

يتحكم هيكل النافذة في الحدود والحشوة وترتيب المناطق الثلاث، ويملأ المستدعي كل واحدة منها. تسمي أطر عمل أخرى هذه خانات (slots)؛ وفي React هي مجرد props. الرمز <>...</> حول الزرين جزء، يجمعهما دون إضافة عنصر زائد. ونافذة حوار حقيقية ستُعرض أيضًا داخل document.body عبر بوابة لتظهر فوق الصفحة.

انقل <p> إلى الـ prop المسماة title فيظهر نص الجسم في الترويسة: المكوّن يقرر أين تذهب كل prop، والمستدعي يقرر فقط ما يوضع فيها.

children كدالة

أحيانًا يملك المغلّف حالة ما وينبغي أن يقرر المستدعي كيف تُرسم. بدلًا من عنصر، يمرر المستدعي دالة على أنها children، ويستدعيها المغلّف بالقيم. يُسمى هذا النمط render prop.

يرسم أحد Toggle زرًا ويرسم الآخر مربع اختيار، من المنطق نفسه. كانت render props الطريقة الرئيسية لمشاركة المنطق ذي الحالة قبل الخطافات. اليوم يكون الخطاف المخصص مثل useToggle() أوضح عادة، لكنك ما زلت سترى render props في مكتبات القوائم والنماذج والحركة.

واجهة Children وcloneElement

تصدّر React كائن Children فيه أدوات مساعدة للمرور على children: Children.map وChildren.forEach وChildren.count وChildren.toArray وChildren.only. ومع cloneElement، الذي ينسخ عنصرًا بـ props جديدة، تتيح للأب فحص ما أُعطي وتغييره. يدرجها فريق React كواجهات قديمة: ما زالت تعمل، لكن ينبغي للكود الجديد تجنّبها.

السبب أنها لا ترى إلا العناصر المكتوبة مباشرة بين الوسمين. لا تستطيع رؤية ما تعرضه تلك العناصر.

تعرض القائمة أربعة عناصر، لكن وحدة التحكم تقول Children.count = 3، لأن TwoMore ابن واحد مهما كان عدد العناصر التي يعرضها. ويسلّم cloneElement أيضًا الـ prop المسماة style إلى TwoMore، الذي يتجاهلها، فلا يُلوَّن العنصران الثالث والرابع. وأي شخص يعيد هيكلة بضعة عناصر <li> إلى مكوّن يكسر الأب دون أن يلمسه.

الحل هو التوقف عن العبث بالأبناء وتمرير البيانات بدلًا من ذلك:

function NumberedList({ items }) {
    return (
        <ol>
            {items.map((item, i) => (
                <li key={item.id} style={{ color: i % 2 ? 'gray' : 'black' }}>
                    {item.label}
                </li>
            ))}
        </ol>
    );
}

الآن تملك القائمة عرض كل صف، ولا شيء يعتمد على طريقة كتابة المستدعي لـ JSX. عندما يحتاج الأب إلى مشاركة قيم مع أبناء متداخلين بعمق (تبويب محدد، أو سمة)، استخدم السياق بدلًا من نسخ props عليهم.

تحديد نوع children في TypeScript

في TypeScript، حدّد نوع children على أنه React.ReactNode. يغطي كل ما يمكن لـ React عرضه: العناصر والنصوص والأرقام ومصفوفاتها وnull وundefined والقيم المنطقية.

import type { ReactNode } from 'react';

type CardProps = {
    title: string;
    children: ReactNode;
};

function Card({ title, children }: CardProps) {
    return (
        <section>
            <h3>{title}</h3>
            {children}
        </section>
    );
}

أما render prop فحدّد نوعها كالدالة التي هي عليه: children: (on: boolean, toggle: () => void) => ReactNode. واجعل children اختيارية (children?: ReactNode) عندما يكون للمكوّن معنى وهو فارغ أيضًا.

أخطاء شائعة

نسيان عرض children. إذا قبل مكوّن أبناء لكنه لم يضع {children} في مخرجاته أبدًا، يختفي المحتوى بصمت. لا شيء يحذّرك.

استدعاء children كدالة وهي ليست كذلك. لا تعمل children() إلا عندما يمرر المستدعي دالة. إذا كان مكوّن يتوقع render prop، فاذكر ذلك في اسمه أو توثيقه، أو اقبل prop مسماة مثل render ليكون القصد واضحًا.

تعديل children. العناصر للقراءة فقط. تجمّدها React أثناء التطوير، فيرمي الإسناد إلى children.props خطأ هناك. ابنِ مخرجات جديدة بدلًا من ذلك.

الأسئلة الشائعة

ما هي props.children في React؟

هي المحتوى المكتوب بين وسمي فتح المكوّن وإغلاقه. في <Card><p>Hi</p></Card> تستقبل الدالة Card العنصر <p> على أنه props.children وتقرر أين تعرضه.

هل children prop خاصة؟

فقط في طريقة تمريرها. تضع JSX المحتوى المتداخل في prop اسمها children، لكنها داخل المكوّن prop عادية. يمكنك أيضًا تمريرها صراحة، كما في <Card children={<p>Hi</p>} />، وتعمل بالطريقة نفسها.

كيف أمرر أكثر من كتلة محتوى إلى مكوّن؟

استخدم props مسماة للكتل الإضافية. يمكن للـ prop أن تحمل JSX تمامًا كما تفعل children، فيمنح <Modal title={<h2>Delete?</h2>} footer={<button>OK</button>}>Body</Modal> المكوّن ثلاث خانات.

هل أستخدم Children.map وcloneElement؟

تجنّبهما في الكود الجديد. لا تريان إلا العناصر المكتوبة مباشرة بين الوسمين، لا ما تعرضه تلك العناصر، فتنكسران بمجرد أن يغلّف أحدهم ابنًا في مكوّن آخر. مرّر مصفوفة بيانات كـ prop، أو استخدم السياق، بدلًا من ذلك.

ما نوع children في TypeScript؟

استخدم React.ReactNode. يغطي كل ما يمكن لـ React عرضه: العناصر والنصوص والأرقام والمصفوفات وnull وundefined والقيم المنطقية.

رسم توضيحي للغات البرمجة في Coddy

تعلّم البرمجة مع Coddy

ابدأ الآن