Fragments and Nested Trees
A component call returns one JavaScript value. A fragment is one React value that can contain several sibling nodes without creating another browser element around them.
function ChapterHeading() {
return (
<>
<p>Chapter 3</p>
<h1>JSX Is Real React Code</h1>
</>
);
}The <> and </> tags form the short fragment syntax. React follows both children. React DOM creates the paragraph and heading, but no fragment DOM node.
Fragments solve React grouping. They do not replace useful HTML parents.
Inspect the Host Result
Render ChapterHeading inside a header.
function App() {
return (
<header>
<ChapterHeading />
</header>
);
}The host tree is equivalent to this structure.
<header>
<p>Chapter 3</p>
<h1>JSX Is Real React Code</h1>
</header>There is no element between header and p. The fragment only groups the two child element descriptions in the React result.
This affects CSS selectors based on direct children.
header > h1 {
color: #61dafb;
}The selector still matches because no wrapper was added.
A fragment participates in the React tree but does not create a host DOM element.
Use a Real Element for Document Meaning
This content has a clear section relationship.
function LessonOverview() {
return (
<section aria-labelledby="lesson-overview-title">
<h2 id="lesson-overview-title">Lesson overview</h2>
<p>Fragments and nested trees</p>
</section>
);
}The section communicates document structure and gives the heading an associated region. Replacing it with a fragment removes that semantic parent.
Use a host element when the parent needs any of these roles.
- document semantics
- a CSS class or layout rule
- an event handler
- an accessible name or state
- a DOM ref
- a host property such as
hidden
A fragment cannot receive className or a normal DOM event prop because there is no host node on which to place them.
<Fragment className="panel">...</Fragment>React does not turn that fragment into a styled container.
Choose a fragment only when React needs grouping and the browser document needs no parent element.
Avoid Wrappers Added Only for JSX Syntax
A component may need two table cells.
function LessonCells() {
return (
<>
<td>Fragments</td>
<td>12 min</td>
</>
);
}The row can use the component.
<tr>
<LessonCells />
</tr>The host result places two td elements directly inside tr. A div wrapper would produce invalid table structure.
Lists have a different requirement. Each repeated item should still be a list item.
<ul>
<li>Expressions Inside JSX</li>
<li>Attributes and Styles</li>
</ul>A fragment must not be used to place bare text and headings directly inside a ul. The HTML list requires li children. Fragments do not suspend host nesting rules.
The Short Syntax Accepts No Props
This is the concise form.
<>
<dt>Fragment</dt>
<dd>A React grouping value</dd>
</>There is no opening tag name where props can be written. The following form is invalid syntax.
< key={term.id}>
<dt>{term.name}</dt>
<dd>{term.definition}</dd>
</>Import the named Fragment component when the fragment needs a key.
import { Fragment } from "react";<Fragment key={term.id}>
<dt>{term.name}</dt>
<dd>{term.definition}</dd>
</Fragment>The key identifies the group among sibling list results. The named fragment form accepts that key.
A Fragment Can Be a Component's Root Result
This component returns three host siblings.
function LessonMetadata() {
return (
<>
<span>Chapter 3</span>
<span>Lesson 3</span>
<span>12 min</span>
</>
);
}The component still returns one React value. The parent receives the three host nodes at the component's position.
Whether those spans need a parent depends on the caller.
<div className="lesson-metadata">
<LessonMetadata />
</div>The parent supplies the layout container. LessonMetadata supplies only the items.
This can be appropriate when the component always lives inside a parent that provides the group. If the metadata needs an accessible label or layout role, give the component a real container instead.
Fragments Do Not Isolate CSS
The fragment does not create a styling scope.
function LessonMetadata() {
return (
<>
<span className="label">Chapter 3</span>
<span className="label">Lesson 3</span>
</>
);
}Selectors from the surrounding page can match both spans normally. Inherited CSS comes from their actual DOM parent, not from the fragment.
If the component needs a local layout context, use a host element with a class.
function LessonMetadata() {
return (
<div className="lesson-metadata">
<span>Chapter 3</span>
<span>Lesson 3</span>
</div>
);
}The div is justified by a layout requirement. It is not present only to satisfy a JSX parser.
Fragments Do Not Stop Event Propagation
Events propagate through the actual host tree. A fragment adds no DOM event target.
<section onClick={handleSectionClick}>
<>
<button type="button">Open</button>
<button type="button">Save</button>
</>
</section>Click events from both buttons can propagate to the section. There is no fragment node where a listener can be attached or propagation can stop.
The fragment rule is structural. No DOM node means no DOM listener location.
Nested Components Can Return Different Root Types
LessonNotice can return a paragraph while LessonList returns a list.
function LessonArea() {
return (
<section>
<LessonNotice />
<LessonList />
</section>
);
}React resolves each component into its returned React nodes. The final host tree must still be valid under the section.
LessonArea component
section host element
LessonNotice component
p host element
LessonList component
ul host elementComponent nesting and host nesting remain separate views of the same rendered work.
Do Not Add a Fragment Around One Child
This fragment has no grouping work.
function LessonTitle() {
return (
<>
<h2>Fragments</h2>
</>
);
}Return the child directly.
function LessonTitle() {
return <h2>Fragments</h2>;
}An unnecessary fragment usually has little runtime cost, but it adds syntax and suggests that multiple siblings or grouping behavior exists when it does not.
Decide with the Host Tree
Before choosing a wrapper, write the required DOM relationship.
article
header
p
h2
pThe header is a useful semantic parent. A fragment should not replace it.
For table cells, the required relationship is different.
tr
td
tdA fragment-returning component can supply those sibling cells without inserting an invalid node.
Inspect the Elements panel after rendering. The actual host tree should match the intended HTML structure.
Lesson Check
The fragment decision now follows one direct test.
React needs one grouping value
browser document needs a parent -> use an HTML element
browser document needs sibling nodes only -> use a fragmentSource Notes
- React reference,
Fragment - React documentation, Writing Markup with JSX
- MDN, HTML elements reference
- MDN, HTML table basics