Vijit Ail Software Engineer at toothsi. I work with React and NodeJS to build customer-centric products.

React Fragments: An overview

5 min read 1473

Fragments React Web Nocdn

React Fragments are a simple yet elegant feature that was released with React v16.2.0. Just comprehending its existence will enable you to write better React components and save a ton of time when creating and styling layouts.

This tutorial is designed to help you understand React Fragments and various use cases where it would come in handy.

Here’s what we’ll cover:

What are React Fragments?

Fragments are a modern syntax for adding multiple elements to a React Component without wrapping them in an extra DOM node.

React Fragments do not produce any extra elements in the DOM, which means that a Fragment’s child components will be rendered without any wrapping DOM node. React Fragments enable you to group multiple sibling components without introducing any unnecessary markup in the rendered HTML.

Fragments in React layouts

React Fragments serve as a cleaner alternative to using unnecessary divs in your code.

Consider the following example to create a simple layout of rows and columns using Flexbox:

import "./styles.css";

const Row = ({ children }) => <div className="row">{children}</div>;

const Column = ({ children }) => <div className="col">{children}</div>;

const Box = ({ color }) => (
  <div className="box" style={{ backgroundColor: color }}></div>
);

export default function App() {
  return (
    <Row>
      <Column>
        <Box color="#007bff" />
      </Column>
      <Column>
        <Box color="#fc3" />
      </Column>
      <Column>
        <Box color="#ff3333" />
      </Column>
    </Row>
  );
}

Each Row renders a div with enclosing content aligned in a single row and a Column renders enclosing content in a vertical fashion. Inside every Column, there is a Box component that renders a simple div with a fixed-width container and a background color passed as props to it.

/* styles.css */
.row {
  display: flex;
}
.col {
  flex: 1;
}
.box {
  min-width: 100px;
  min-height: 100px;
}

The above code renders three columns in a single row, as shown below:

We made a custom demo for .
No really. Click here to check it out.

Code Render Three Color Columns Row

Let’s refactor the above code to separate the first two columns in a different component called ChildComponent. Imagine this as a reusable component that you might want to decouple.

export default function App() {
  return (
    <Row>
      <ChildComponent />
      <Column>
        <Box color="#ff3333" />
      </Column>
    </Row>
  );
}

const ChildComponent = () => (
  <div>
    <Column>
      <Box color="#007bff" />
    </Column>
    <Column>
      <Box color="#fc3" />
    </Column>
  </div>
);

The expected result should be the same as before, but it isn’t. Decoupling the first two columns in a separate component ChildComponent breaks the layout:

Layout Break Child Component Result

The ChildCompoent has a div wrapping all its JSX elements to group them together. However, that extra div causes a break in the layout because the browser thinks it’s a part of the layout. Your browser doesn’t know that you’ve added that div to avoid running into an error and it is used as merely a wrapper for your enclosing HTML.

As the component tree nests deeper, it can be difficult to debug and trace where the extra nodes are coming from. Similarly, if you’re using CSS Grids to style and design your layouts, unnecessary divs could cause your layout to break. An easy fix is to wrap your component’s JSX in a React Fragment instead.

import React from 'react';

const ChildComponent = () => (
  <React.Fragment>
    <Column>
      <Box color="#007bff" />
    </Column>
    <Column>
      <Box color="#fc3" />
    </Column>
  </React.Fragment>
);

There are many ways to create and render Fragments. You can create a Fragment by using the Fragment property on the imported React object, as shown above. You can also import a Fragment from React as a React component and use it in a similar fashion.

import React, {Fragment} from 'react';

const ChildComponent = () => (
  <Fragment>
    <Column>
      <Box color="#007bff" />
    </Column>
    <Column>
      <Box color="#fc3" />
    </Column>
  </Fragment>
);

Finally, you can create a React Fragment on the fly using the shorthand syntax to wrap components using an empty HTML element like syntax. This is the cleanest and easiest way to use Fragments; it almost feels like you’re using a regular HTML element.

const ChildComponent = () => (
  <>
    <Column>
      <Box color="#007bff" />
    </Column>
    <Column>
      <Box color="#fc3" />
    </Column>
  </>
);

Using any of the above three methods brings back the original layout because it eliminates any pointless div in your DOM.

Rendering lists with React Fragments

Let’s look at another common use case for Fragments. Let’s say you want to render a list of items on the page. This list could be static, generated from a local JSON file, or retrieved from an API.

For brevity’s sake, we’ll use a static list:

import React from 'react';

const items = ["Item 1", "Item 2", "Item 3"];

const ItemRenderer = ({ item }) => (
  <div>
    <p>Rendering item:</p>
    <p>{item}</p>
  </div>
);

const renderItem = () => items.map((item, index) =>
  <ItemRenderer key={index} item={item} />
);

Here you’re simply looping through the items array and passing each item as props to the ItemRenderer component, which renders every single item on the page. If you inspect the above code on a browser, you’ll have the following DOM structure:

<div>
  <p>Rendering item:</p>
  <p>Item 1</p>
</div>
<div>
  <p>Rendering item:</p>
  <p>Item 2</p>
</div>
<div>
  <p>Rendering item:</p>
  <p>Item 3</p>
</div>

Each item gets rendered in a parent div that has no significance as a wrapper. Since there is no styling or data attached to the enclosing div, it can be safely replaced by a React Fragment, as shown below:

 import React from 'react';

const items = ["Item 1", "Item 2", "Item 3"];

const ItemRenderer = ({ item }) => (
  <>
    <p>Rendering item:</p>
    <p>{item}</p>
  </>
);

const renderItem = () => items.map((item, index) =>
  <ItemRenderer key={index} item={item} />
);

The DOM structure looks much cleaner now:

  <p>Rendering item:</p>
  <p>Item 1</p>
  <p>Rendering item:</p>
  <p>Item 2</p>
  <p>Rendering item:</p>
  <p>Item 3</p>

This is a very simplified use case where you might be rendering an extra div on your DOM. The larger your lists are, the more significant the impact.

As your application becomes larger in size and complex in architecture, you might find yourself rendering a significant amount of unnecessary divs to render large lists in your application. This could bloat your HTML, causing performance issues on older devices.

It may not be that significant at all, but rendering unnecessary HTML elements is always a bad practice. If you have a generic list component for your application, consider using Fragments as wrappers to avoid abstracting away from clean code and semantics.

Finally, Fragments enable you to pass a key property as props, but note that it’s the only prop it can accept:

import React from 'react';

const items = ["Item 1", "Item 2", "Item 3"];

const ItemRenderer = () => (
  <React.Fragment>
    <h1>List of all items:</h1>
    {items.map((item, index) => (
      <React.Fragment key={index}>
        <p>Rendering Item:</p>
        <p>{item}</p>
      </React.Fragment>
    )}
  </React.Fragment>
);

You can only pass props to your Fragment if you’re rendering it as shown above. Props can’t be passed to your Fragments if you’re using the shorthand notation. A good practice is to use React.Fragment or Fragment syntax when you need to pass keys, especially when rendering using a loop.

Conclusion

Fragments allow you to write cleaner, readable and maintainable code. They are not a replacement for divs in your HTML, but they offer a better approach to structuring and rendering your markup if you’re using unnecessary divs in your code.

You can avoid issues that break your layouts or potentially optimize your markup rendering time using Fragments. However, you should only use them when needed. If you need a wrapper to your JSX for styling, use a div instead.

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

Vijit Ail Software Engineer at toothsi. I work with React and NodeJS to build customer-centric products.

Testing accessibility with Storybook

One big challenge when building a component library is prioritizing accessibility. Accessibility is usually seen as one of those “nice-to-have” features, and unfortunately, we’re...
Laura Carballo
4 min read

2 Replies to “React Fragments: An overview”

  1. Great article. The examples makes it clear.

    I’ve always use the shorthand and didn’t realise props can be passed in to list as well.
    I’m gonna to try next time.

    Thanks Vijit.

  2. You used very simple examples and demonstrations. I now understand what the documentation was referring to as adding a node. Thanks!

Leave a Reply