What is fragment in React
React Fragment is a component that groups multiple JSX elements into one return without adding any node to the DOM.
Theory
TL;DR
- Think plastic wrap around groceries: holds items together for carrying, but disappears once unpacked, nothing in the final HTML
<div>adds a real element; Fragment adds zero- Short syntax
<>and full<Fragment>produce identical output; only<Fragment>acceptskey - Need one root but a clean DOM: Fragment. Need styling or event handlers on the wrapper:
<div>
Quick example
// div wrapper breaks table layout
function BadRow() {
return (
<div>
<td>Name</td>
<td>Email</td>
</div>
);
}
// DOM: <div><td>Name</td><td>Email</td></div> (invalid HTML)
// Fragment keeps DOM clean
function GoodRow() {
return (
<>
<td>Name</td>
<td>Email</td>
</>
);
}
// DOM: <td>Name</td><td>Email</td>React requires every component to return exactly one root element. Fragment satisfies that rule without showing up in the browser HTML.
Key difference
<div> solves the "one root" problem but adds a real node to the DOM. That node has layout consequences: it breaks <td> children inside a <tr>, interrupts flex or grid containers, and adds unwanted nesting to semantic HTML. Fragment solves the same problem with zero DOM cost.
When to use
- Multiple sibling elements from one component: Fragment
- Table rows or list items where extra wrappers break layout: Fragment
- Mapping over a list and grouping two siblings per item:
<Fragment key={item.id}> - Wrapper needs
className,style, or a click handler:<div>or a semantic element
Comparison table
| Characteristic | <div> | <Fragment> / <> |
|---|---|---|
| DOM nodes added | 1 | 0 |
Supports key prop | Yes | Yes (full syntax only) |
Accepts className, style | Yes | No |
| Affects layout | Yes | No |
| When to use | Needs styling or events | Clean grouping only |
How it works
Babel converts both <> and <Fragment> to React.createElement(React.Fragment, null, ...children). During reconciliation React skips DOM node creation for Fragment and mounts children directly under the parent. That is why both syntaxes produce identical HTML output.
Common mistakes
Missing key on Fragment in lists:
// Wrong: no key, React warns about unstable keys
items.map(item => (
<>
<li>{item.name}</li>
<li>{item.price}</li>
</>
));
// Correct: key goes on Fragment, not the children
items.map(item => (
<Fragment key={item.id}>
<li>{item.name}</li>
<li>{item.price}</li>
</Fragment>
));<> cannot accept props. Switch to <Fragment> whenever you need a key.
Expecting props to work on Fragment:
// Ignored: Fragment does not render, style has no effect
<Fragment style={{ color: 'red' }}>
<p>Not styled</p>
</Fragment>Every prop except key is silently ignored. Use <div> if the wrapper needs styling.
Unnecessary nesting:
// Redundant: outer Fragment wraps a single child
return (
<>
<Fragment>
<h1>Title</h1>
</Fragment>
</>
);
// Just return <h1>Title</h1> directlyReal-world usage
- React Table v8: grouping
<td>cells inside<tr>without extra nodes - Next.js page components: clean JSX to avoid hydration mismatches from unexpected wrapper divs
- Material-UI: composite components that render sibling elements inside a parent container
- Conditional rendering of siblings without accumulating nested
<div>wrappers
Follow-up questions
Q: What is the difference between <Fragment> and <>?
A: Output is identical. <> is shorthand. The only reason to write <Fragment> is when you need to attach a key prop.
Q: Can Fragment accept a key prop?
A: Yes, but only in full syntax: <Fragment key="...">. Adding attributes to <> is a syntax error.
Q: Why not replace every <div> with Fragment?
A: Fragment cannot carry className, style, or event listeners. When the wrapper itself has to do something, it must be a real element.
Q: Does Fragment appear in React DevTools?
A: Yes, it shows as a "Fragment" node in the component tree. Children remain fully inspectable and debuggable.
Q: How does React handle Fragment in the fiber tree?
A: Fragment is a composite fiber with no host component, so the renderer skips createInstance and mounts children directly onto the parent DOM node. The key prop feeds into the diffing algorithm the same way it does on any other element.
Examples
Grouping table cells
The table case is where a stray <div> causes the most confusion in code reviews - layout breaks and it takes a while to spot the invalid HTML.
function UserRow({ user }) {
return (
<tr>
<Fragment key={user.id}>
<td>{user.name}</td>
<td>{user.email}</td>
<td>
<button>Edit</button>
<button>Delete</button>
</td>
</Fragment>
</tr>
);
}
// Result: <tr><td>name</td><td>email</td><td>...</td></tr>
// No extra nodes, valid HTMLkey on Fragment ensures stable reconciliation when UserRow is used inside .map().
Conditional sibling rendering
function UserProfile({ user, isAdmin }) {
return (
<>
<h2>{user.name}</h2>
<p>{user.email}</p>
{isAdmin && (
<>
<p>Role: Admin</p>
<button>Manage Users</button>
</>
)}
</>
);
}Both levels use <>. The DOM only contains elements that actually render, no wrapper accumulation.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.