ReactFragments

Fragments

React requires every component to return a single root element. The obvious solution — wrapping everything in a <div> — works, but it pollutes the DOM with nodes that exist solely to satisfy React's rule. Those extra nodes can break CSS layouts, invalidate HTML semantics, and add pointless weight to the page. Fragments solve this cleanly: they let you group elements without adding any node to the DOM.

The Problem: Wrapper Divs

Before fragments existed, developers wrapped siblings in a <div>. Consider a component that renders two table cells:

JSX
// ❌ Extra <div> breaks table structure
function TableCells({ item }) {
  return (
    <div>
      <td>{item.name}</td>
      <td>{item.price}</td>
    </div>
  )
}

// Usage inside a table row:
<tr>
  <TableCells item={product} />
</tr>

This produces invalid HTML — a <div> cannot be a direct child of <tr>. Browsers try to recover by moving the <div> outside the table, breaking the layout entirely. Fragments solve this:

JSX
// ✅ Fragment — zero DOM nodes added
function TableCells({ item }) {
  return (
    <>
      <td>{item.name}</td>
      <td>{item.price}</td>
    </>
  )
}

// The rendered HTML is now valid:
// <tr>
//   <td>Apple</td>
//   <td>$1.99</td>
// </tr>
Two Syntaxes

There are two ways to write a Fragment. They are functionally identical except for one important difference covered in the next section:

JSX
import React from 'react'

// Syntax 1: Shorthand (most common)
function ShorthandFragment() {
  return (
    <>
      <h1>Title</h1>
      <p>Paragraph</p>
    </>
  )
}

// Syntax 2: Explicit React.Fragment
function ExplicitFragment() {
  return (
    <React.Fragment>
      <h1>Title</h1>
      <p>Paragraph</p>
    </React.Fragment>
  )
}
Note
You can also import Fragment directly: `import { Fragment } from 'react'` and then write `<Fragment>...</Fragment>`. All three forms compile to the same output.
When You Need the Explicit Syntax: the key Prop

The shorthand <></> syntax does not support attributes. The one case where you need the explicit <React.Fragment> form is when rendering a list of fragments that each require a key prop:

JSX
// ❌ Shorthand cannot accept key
function DefinitionList({ terms }) {
  return (
    <dl>
      {terms.map((term) => (
        <>                          {/* Can't put key here */}
          <dt>{term.word}</dt>
          <dd>{term.definition}</dd>
        </>
      ))}
    </dl>
  )
}

// ✅ Explicit Fragment supports the key prop
import { Fragment } from 'react'

function DefinitionList({ terms }) {
  return (
    <dl>
      {terms.map((term) => (
        <Fragment key={term.id}>
          <dt>{term.word}</dt>
          <dd>{term.definition}</dd>
        </Fragment>
      ))}
    </dl>
  )
}
Practical Use Cases

Fragments are useful in any situation where extra DOM nodes would be problematic or redundant:

JSX
// 1. Table rows — <tr> can only contain <td>/<th>
function DataRow({ row }) {
  return (
    <>
      <td>{row.date}</td>
      <td>{row.amount}</td>
      <td>{row.status}</td>
    </>
  )
}

// 2. List items returned from a helper
function ContactInfo({ contact }) {
  return (
    <>
      <li>{contact.email}</li>
      <li>{contact.phone}</li>
    </>
  )
}

// 3. Conditional blocks without extra wrappers
function AlertArea({ alerts }) {
  return (
    <div className="alerts">
      {alerts.map((alert) => (
        <Fragment key={alert.id}>
          <AlertIcon type={alert.type} />
          <AlertMessage text={alert.message} />
          <Divider />
        </Fragment>
      ))}
    </div>
  )
}

// 4. Multiple elements returned from a helper function
function renderBreadcrumbs(path) {
  return path.map((segment, i) => (
    <Fragment key={segment.href}>
      {i > 0 && <span> / </span>}
      <a href={segment.href}>{segment.label}</a>
    </Fragment>
  ))
}
The DOM Output

To see the difference fragments make, compare the DOM output of a Fragment vs a wrapper div for a simple two-element component:

JSX
// With a wrapper div:
function WithDiv() {
  return (
    <div>
      <h2>Section</h2>
      <p>Content</p>
    </div>
  )
}

// With a Fragment:
function WithFragment() {
  return (
    <>
      <h2>Section</h2>
      <p>Content</p>
    </>
  )
}

DOM output of WithDiv:

<div>
  <h2>Section</h2>
  <p>Content</p>
</div>

DOM output of WithFragment:

<h2>Section</h2>
<p>Content</p>
Performance: Why Wrapper Divs Are Not Free

Every DOM node has a cost. The browser must:

  • Allocate memory for the node

  • Recalculate layout (reflow) when nodes change

  • Apply CSS rules that might match the new element

  • Include it in accessibility trees that assistive technologies traverse

In an application that renders thousands of list items or table rows, unnecessary wrapper elements add up. Fragments keep the DOM lean. They also prevent CSS issues — flexbox and grid layouts, for example, are sensitive to unexpected wrapper elements that break the direct parent-child relationship required for flex/grid items to work.

Warning
A common mistake when adopting fragments: replacing meaningful semantic wrappers with fragments. If a `<div>` is carrying CSS classes, semantic meaning, or event handlers, it should stay. Fragments replace only `<div>` wrappers that exist **solely** to satisfy React's single-root rule.
Tip
When in doubt: if you would not add the wrapper element to plain HTML for any styling or semantic reason, use a Fragment instead.
Summary
  • Fragments let you group multiple elements without adding a DOM node

  • Shorthand <></> is the common case; <Fragment key={...}> is needed for keyed lists

  • Critical for valid HTML inside tables (<tr>/<td>), lists (<ul>/<li>), and other elements with strict child rules

  • Keeps the DOM clean — avoids extra divs that break CSS flex/grid layouts

  • Import Fragment from 'react' when you need the explicit form: import { Fragment } from 'react'