React is one of the most popular JavaScript libraries. React fragments solves the problem of returning multiple elements without the need of wrapping them in an extra Node (usually a div).
The fragments feature was introduced in v 16.2 of React. In this tutorial, you will learn how to use React fragments to add multiple elements to a React component, let’s get started!
Table of contents #
What are React fragments? #
React fragments is a feature included in React to return more than one HTML element from a React Component. It is a common pattern in React for a component to return multiple elements, but with the usual React component syntax and return, it always expects only a single HTML element to be returned. To comply with this requirement, React developers usually wrap the HTML with an extra div element.
On the other hand, fragments let you group a list of children without adding extra nodes (HTML Elements) to the DOM, which results in a shallow DOM tree.
Example App - HackerNews #
For this guide, you will use an existing simple React application. It uses the unofficial HackerNews API provided by Algolia to get the Hackernews front-page stories. The app is built on React 18.2 and below is the screenshot of the app in action:
You can find the app running on Netlify and the code is available on GitHub for your reference.
If you look at the HackerNewsStories component the code looks as follows:
import { useState, useEffect } from 'react';
const HackerNewsStories = () => {
const [stories, setStories] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchStories = async () => {
try {
const data = await (await fetch('https://hn.algolia.com/api/v1/search_by_date?tags=front_page&hitsPerPage=20')).json();
setStories(
data.hits.sort((story, nextStory) => (story.points < nextStory.points ? 1 : -1))
);
setError(null);
} catch (err) {
setError(err.message);
setStories(null);
} finally {
setLoading(false);
}
};
fetchStories();
}, []);
return (
<div className="wrapper">
<h2>Latest HN Stories</h2>
{loading && <div>HackerNews frontpage stories loading...</div>}
{error && <div>{`Problem fetching the HackeNews Stories - ${error}`}</div>}
<div className="stories-wrapper">
{stories &&
stories.map(({ objectID, url, title, author, points }) => (
title && url &&
<div className='stories-list' key={objectID}>
<h3><a href={url} target="_blank" rel="noreferrer">{title}</a> - By <b>{author}</b> ({points} points)</h3>
</div>
))}
</div>
</div>
);
};
export default HackerNewsStories;
Let’s say due to the design need or to have lesser depth in the DOM tree you want to remove the div with the class wrapper
. Do you think you can just remove that parent div?
The problem when not using React fragments #
No, because React components do not support returning multiple HTML elements. On the line just below the return you see <div className="wrapper">
which is an extra div that is an extra HTML Node used. It is needed, if you try to remove it you will get an error. For instance, if you change the above return part to the following code to remove the div with class wrapper:
return (
<h2>Latest HN Stories</h2>
{loading && <div>HackerNews frontpage stories loading...</div>}
{error && <div>{`Problem fetching the HackeNews Stories - ${error}`}</div>}
<div className="stories-wrapper">
{stories &&
stories.map(({ objectID, url, title, author, points }) => (
title && url &&
<div className='stories-list' key={objectID}>
<h3><a href={url} target="_blank" rel="noreferrer">{title}</a> - By <b>{author}</b> ({points} points)</h3>
</div>
))}
</div>
);
It will result in the following error:
Basically, it means you cannot return more than one HTML element from a React Component. This is the problem solved by React fragments, which will be discussed next.
React fragments solve this problem #
To solve this problem of returning more than one HTML element from a React component without wrapping it with another HTML tag/element like a div, you can use React fragments. The same return after using React fragment to return multiple HTML elements will look like the below:
return (
<Fragment> {/* You can also use the shorter syntax of <> */}
<h2>Latest HN Stories</h2>
{loading && <div>HackerNews frontpage stories loading...</div>}
{error && <div>{`Problem fetching the HackeNews Stories - ${error}`}</div>}
<div className="stories-wrapper">
{stories &&
stories.map(({ objectID, url, title, author, points }) => (
title && url &&
<div className='stories-list' key={objectID}>
<h3><a href={url} target="_blank" rel="noreferrer">{title}</a> - By <b>{author}</b> ({points} points)</h3>
</div>
))}
</div>
{/* </> is the closing tag for shorter React fragment syntax */}
</Fragment>
);
For this to work, you will need to import Fragment
from react at the top of the component as follows:
import { useState, useEffect, Fragment } from 'react';
The above React component now returns 2 or 3 HTML elements, one H2, one of the two divs for loading or error, and the last div which will render the stories with the CSS class stories-wrapper
. You have easily solved the problem and it is possible to return more than one HTML element from a React component now.
As seen above you can use the full React fragment syntax or the short syntax with just <>
and </>
. You will need to use the full syntax if you want to make use of Keyed fragments, where every fragment has a unique key.
To better understand the HTML structure, below is the comparison between before using React fragments with a div
wrapper and after using React fragments is shown below:
It has multiple advantages, for instance, the depth of the HTML node tree will be lesser. In addition to that if you are creating a subcomponent structure like an HTML table you can get the exact HTML you are after. Also if you have a style sheet targeting elements by their depth, they will work without any change as the HTML will not have any extra layer of div or other HTML elements.
The code change demonstrated in this blog post is available as a pull request for your reference. You can also see the app running with react fragments on Netlify. Start using React fragments now.
Conclusion #
In this guide, you learned what React fragments are. Then you were introduced to a problem of trying to return multiple HTML elements from a regular React Component which got stuck due to an error. Then you employed React fragments to get over the problem and with an easy-to-use Syntax you were able to return multiple elements for a React Component.
I hope you learned something new after reading this, keep learning!