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

Fragment في React: الفرق بين <>...</> و<Fragment> مع أمثلة

يجمع Fragment في React عدة عناصر في قيمة إرجاع واحدة دون إضافة عقدة إلى الصفحة. تعلّم الصيغة المختصرة <>...</>، ومتى تحتاج إلى <Fragment key>، ولماذا تهم الأجزاء داخل الجداول والقوائم.

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

يتيح Fragment في React لمكوّن أن يُرجع عدة عناصر دون تغليفها في <div> إضافي. اكتب <> قبل العنصر الأول و</> بعد الأخير، فتضع React العناصر مباشرة داخل الأب، دون أي عقدة خاصة بها في الصفحة.

يُرجع كل Greeting عنوانًا وفقرة جنبًا إلى جنب. احذف السطرين <> و</> فتعرض المعاينة خطأ بناء بدلًا من ذلك، لأن الدالة تحاول الآن إرجاع قيمتين.

لماذا يحتاج المكوّن إلى جذر واحد

JSX طريقة أجمل لكتابة استدعاءات الدوال. يتحول <h2>Hi</h2> تقريبًا إلى jsx('h2', { children: 'Hi' })، أي تعبير واحد. يمكن لعبارة return أن تُرجع قيمة واحدة، فيكون وسمان شقيقان دون شيء يحيط بهما مثل كتابة return a b: يتوقف المترجم برسالة "Adjacent JSX elements must be wrapped in an enclosing tag".

قبل وجود الأجزاء، كان الحل <div> مغلّفًا. هذا يعمل، لكن div عنصر حقيقي. يظهر في DOM، ويشارك في تخطيط CSS، وبعض الآباء لا يقبلونه كابن أصلًا. أما الجزء فيلبّي قاعدة الجذر الواحد ثم يختفي.

يمكنك أن ترى أنه لا يضيف شيئًا. يعرض المثال أدناه العنصرين نفسيهما عبر جزء وعبر div، ثم يعدّ الأبناء المباشرين لكل حاوية.

تطبع وحدة التحكم 2 للجزء، أي العنصرين span، و1 للعنصر div، الذي يغلّفهما. في حاوية flex أو grid يحدد هذا الفرق ما إذا كان العنصران span سيُرتَّبان كعنصرين منفصلين أم سيُجمعان في عنصر واحد.

الصيغة المختصرة ومكوّن Fragment

هناك طريقتان لكتابة جزء، وتتحولان إلى الشيء نفسه:

import { Fragment } from 'react';

// Short syntax, no import needed
<>
    <dt>React</dt>
    <dd>A library for building user interfaces</dd>
</>

// Long form
<Fragment>
    <dt>React</dt>
    <dd>A library for building user interfaces</dd>
</Fragment>

استخدم <>...</> في كل مكان تقريبًا. ولا تلجأ إلى <Fragment> إلا في حالة واحدة: عندما يحتاج الجزء إلى key. لا تقبل الصيغة المختصرة سمات، فلا تُعد <key={id}> صيغة JSX صالحة. وقد ترى أيضًا <React.Fragment> في الكود الأقدم؛ وهو المكوّن نفسه لكن عبر الاستيراد الافتراضي React.

أجزاء ذات مفاتيح في القوائم

عندما تعرض قائمة بـ map، يحتاج كل عنصر إلى key لتتمكن React من تتبعه بين مرات العرض (تشرح صفحة القوائم والمفاتيح السبب). إذا كان كل عنصر مجموعة من العناصر بدلًا من عنصر واحد، يوضع المفتاح على الجزء، فتحتاج إلى الشكل الطويل.

قائمة الوصف هي الحالة الكلاسيكية: كل مدخل يتكون من <dt> و<dd>، وينبغي أن تحتويهما <dl> مباشرة.

انقر Reverse فتتبادل الأزواج أماكنها كوحدات كاملة، لأن لكل زوج مفتاحه الخاص. سيقبل <div> مغلّف حول كل زوج مفتاحًا أيضًا، وهو HTML صالح داخل dl، لكنه يضيف مستوى ثالثًا إلى الترميز يُبقيه الجزء خارجه.

الأجزاء داخل الجداول

الجداول هي حيث يضر المغلّف الشارد أكثر. يتوقع <tr> خلايا <td> و<th> كأبناء مباشرين. إذا غلّف مكوّن يُرجع عدة خلايا تلك الخلايا في <div>، يعامل المتصفح div كخلية واحدة غريبة وتتوقف الخلايا داخله عن الاصطفاف مع الترويسة.

في صف الجزء يظهر السعر تحت Price والمخزون تحت Stock. أما في صف div فتُحشر الخليتان كلتاهما في عمود Price ويبقى عمود Stock فارغًا. في التطوير تسجّل React أيضًا تحذيرًا بأن <div> لا يمكن أن يكون ابنًا لـ <tr>؛ والمعاينة تعمل مثل بناء الإنتاج، فتتخطى هذا الفحص، والتخطيط المكسور هو ما تراه هنا. ومع العرض على الخادم قد يسبب الخطأ نفسه أخطاء في الإماهة (hydration) أيضًا، لأن محلل HTML في المتصفح ينقل div الموضوع في غير مكانه.

تنطبق القاعدة نفسها على <ul> و<ol>، اللذين ينبغي أن يحتويا عناصر <li>، وعلى <select>، الذي ينبغي أن يحتوي عناصر <option>. كلما أرجع مكوّن قطعًا تنتمي مباشرة داخل أب كهذا، فأرجع جزءًا.

الأجزاء أم المصفوفات

يمكن للمكوّن أيضًا أن يُرجع مصفوفة من العناصر، فتعرضها React بالترتيب مثل الجزء. يحتاج كل عنصر في المصفوفة المُرجعة إلى مفتاحه الخاص، تمامًا مثل مخرجات map، لأن React تعامل المصفوفة كقائمة:

function Cells() {
    return [<td key="price">$4</td>, <td key="stock">In stock</td>];
}

هذا يعمل، لكنه أكثر ضجيجًا: فواصل بين العناصر، ومفتاح على كل واحد، وقوس مربع يسهل أن يفوتك عندما يكبر الترميز. استخدم جزءًا لمجموعة ثابتة من العناصر، واترك المصفوفات لما هي عليه بطبيعتها، أي نتيجة المرور على البيانات.

ما لا يستطيعه الجزء

لأن الجزء لا يعرض أي عنصر، فليس لديه مكان يضع فيه صنفًا أو نمطًا أو معالج حدث أو مرجعًا. لا يفعل <Fragment className="row"> شيئًا مفيدًا، والـ prop الوحيدة التي تقرؤها React من الجزء هي key. عندما تحتاج إلى تنسيق المجموعة أو الاستماع إلى النقرات عليها، فأنت تحتاج إلى عنصر حقيقي في النهاية، ولا بأس في ذلك: اختر عنصرًا صالحًا في موضعه، مثل <tbody> لتجميع الصفوف أو <li> ليحمل عنصر قائمة.

يعمل الجزء في أي مكان يعمل فيه العنصر، بما في ذلك داخل العرض الشرطي: يُظهر {show && <>...</>} المجموعة كلها أو يخفيها دفعة واحدة.

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

ما هو Fragment في React؟

Fragment مغلّف يتيح لمكوّن أن يُرجع عدة عناصر كقيمة واحدة دون إضافة عقدة إلى DOM. يضع <><h1 /><p /></> العنصرين h1 وp مباشرة داخل الأب.

ما الفرق بين <> و<Fragment>؟

ينتجان الشيء نفسه. <>...</> هي الصيغة المختصرة. و<Fragment> هو الشكل الطويل الذي تستورده من react، وهو الوحيد الذي يقبل key، وهذا ما تحتاجه عندما تعرض أجزاء داخل قائمة.

لماذا أستخدم Fragment بدلًا من div؟

عنصر div عنصر حقيقي. قد يكسر التخطيطات التي تتوقع أبناء مباشرين (حاويات flex وgrid وul وtable وtr) ويضيف ضجيجًا إلى DOM. أما Fragment فلا يضيف شيئًا.

هل يمكن أن يكون لـ Fragment سمة className أو onClick؟

لا. لا يعرض Fragment أي عنصر، فلا يوجد ما تضع عليه صنفًا أو نمطًا أو معالج حدث. الـ prop الوحيدة التي يقبلها هي key. إذا احتجت إلى أي من ذلك فاستخدم عنصرًا حقيقيًا.

لماذا تظهر لي رسالة "Adjacent JSX elements must be wrapped in an enclosing tag"؟

أرجع مكوّن عنصرين شقيقين دون شيء يحيط بهما. تتحول JSX إلى تعبير واحد، لذا ضع العنصرين الشقيقين داخل <>...</>.

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

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

ابدأ الآن