Fragments
A React component must return a single root element, but real UIs are full of sibling elements that don’t naturally share a parent. Fragments solve this by letting you group children without wrapping them in an extra DOM node. The result is cleaner markup, fewer layout headaches, and HTML that behaves the way the spec intends.
Why a component returns one root
JSX compiles to function calls, and a return statement can only return one value. When you write JSX, the outermost element becomes that single returned value. Returning two adjacent elements is therefore a syntax error:
function Profile() {
// This will NOT compile
return (
<h1>Ada Lovelace</h1>
<p>The first programmer.</p>
);
}
The classic workaround is to wrap everything in a <div>. That works, but it pollutes the DOM with containers that exist only to satisfy React. Over many components this becomes “wrapper-div soup” that complicates CSS and breaks layout primitives like Flexbox, Grid, and <table>.
Using a Fragment
A Fragment is an invisible wrapper. It satisfies the single-root rule while rendering nothing to the DOM. Use it via React.Fragment or the <>...</> shorthand:
import { Fragment } from "react";
function Profile() {
return (
<Fragment>
<h1>Ada Lovelace</h1>
<p>The first programmer.</p>
</Fragment>
);
}
The shorthand syntax is more common because it is concise and reads as “just a group”:
function Profile() {
return (
<>
<h1>Ada Lovelace</h1>
<p>The first programmer.</p>
</>
);
}
Both versions produce identical DOM output — no wrapper element at all:
Output:
<h1>Ada Lovelace</h1>
<p>The first programmer.</p>
Where Fragments shine: valid HTML structures
Some HTML elements have strict parent-child rules. A <tr> may only contain <td>/<th>, and a <td> may contain anything — but a stray <div> between a <table> and its rows is invalid. Fragments let a component return multiple cells without breaking the structure:
function Columns({ row }) {
return (
<>
<td>{row.name}</td>
<td>{row.role}</td>
</>
);
}
function Table({ people }) {
return (
<table>
<tbody>
{people.map((p) => (
<tr key={p.id}>
<Columns row={p} />
</tr>
))}
</tbody>
</table>
);
}
Here <Columns> injects two <td> siblings directly into the <tr>, with no illegal wrapper in between.
Keyed Fragments in lists
When you render a list and each item needs to produce multiple elements, you need a key on the outer group. The <> shorthand cannot take attributes, so you must use the explicit <React.Fragment> form with a key:
function Glossary({ items }) {
return (
<dl>
{items.map((item) => (
// The shorthand <> cannot accept a key here
<Fragment key={item.term}>
<dt>{item.term}</dt>
<dd>{item.definition}</dd>
</Fragment>
))}
</dl>
);
}
This keeps <dt> and <dd> as direct children of <dl> (which is required for valid description lists) while still giving React the stable key it needs to track each pair.
Tip:
keyis the only prop a Fragment accepts. Passing any other attribute (likeclassNameor event handlers) does nothing — Fragments render no element to attach them to.
Shorthand vs. explicit form
| Feature | <>...</> shorthand | <React.Fragment>...</React.Fragment> |
|---|---|---|
| Renders a DOM node | No | No |
Accepts key | No | Yes |
| Requires an import | No | Yes (Fragment) |
| Best for | General grouping | Keyed list items |
Avoiding wrapper-div soup
Reach for a Fragment whenever a <div> would exist purely to group siblings and carries no styling or semantic meaning. Compare the DOM produced by a wrapper-heavy layout versus a Fragment-based one:
// Adds an extra layout node that can disrupt the parent's Grid/Flex flow
function WithDiv() {
return (
<div>
<Label />
<Input />
</div>
);
}
// Children become direct participants of the parent layout
function WithFragment() {
return (
<>
<Label />
<Input />
</>
);
}
If the parent is a CSS Grid expecting <Label> and <Input> as direct grid items, the wrapper <div> collapses them into one cell, whereas the Fragment preserves the intended layout.
Best Practices
- Prefer the
<>...</>shorthand for everyday grouping — it is the cleanest way to satisfy the single-root rule. - Switch to
<Fragment key={...}>whenever a mapped item returns multiple sibling elements that need a key. - Use Fragments to keep table, list, and
<select>markup valid instead of inserting illegal wrapper elements. - Keep a real
<div>(or semantic element) only when it carries styling, semantics, or an event handler — not as a pure grouping crutch. - Remember that Fragments accept no props except
key; reach for a real element when you needclassName,ref, or handlers. - Watch your imports: the shorthand needs none, but
React.Fragment/Fragmentmust be imported to use a key.