React Fragments

Chapter 14 5 mins

Learning outcomes:

  1. What are fragments
  2. Why we need fragments
  3. Creating fragments using Fragment or JSX
  4. Using keys with fragments

What are fragments?

Often times when constructing JSX markup, we might come across the need to encapsulate it around a container element.

This is because we can't return multiple JSX elements from a component as it is, like in the following snippet:

function App() {
   return (
      <h1>A heading</h1>
      <p>A paragraph</p>
   );
}

Remember that a JSX element is simply a call to createElement() and so returning multiple elements means to be returning multiple such expressions as follows:

function App() {
   return (
      React.createElement('h1', null, 'A heading')
      React.createElement('p', null, 'A paragraph')
   );
}

Clearly, this code is invalid and thus we get an error thrown in the previous JSX code.

Now, <div>s have long been used in React to act as this container element, but actually there's no need to go this way.

A <div> unnecessarily populates the DOM by introducing redundant elements into it where those elements don't make sense at all. Remember that we used the <div>s purely for preventing the error that we witnessed above, not that they had an actual purpose in the HTML.

Fortunately, we don't have to rely on a <div> for grouping together React elements into a container. Say hello to fragments.

A fragment is a means of grouping together multiple React elements into a single React element.

Just how the DOM has the idea of document fragments to group DOM nodes into one single node that itself doesn't show up in the DOM, React has one as well.

In React, a fragment operates much like a DOM fragment. It groups multiple React elements into a single unit which can then be treated as a single element itself (in fact, it is an element in React).

However, a fragment does NOT show up in the DOM; it's meant exclusively for React code. This is the cool feature of fragments which solves the very issue with using <div>s as containers, which was polluting the DOM.

Let's now see how to create a fragment in React.

Creating fragments

The react library exports a built-in component called Fragment which represents the fragment element type.

To create a fragment in React, we require this Fragment component. It wraps up the set of elements around which we need a container.

Let's take an example.

In the following code, we use a fragment to replace the container <div> in the code above, encapsulating an <h1> followed by a <p>:

import { Fragment } from 'react';

function App() {
   return (
      <Fragment>
         <h1>A heading</h1>
         <p>A paragraph</p>
      </Fragment>
   );
}

When the <Fragment> here gets rendered out on the document, only <h1> and <p> are rendered into the DOM; the fragment itself, just like user-defined component instances, doesn't make its way into the DOM.

Live Example

This can be confirmed in the illustration below, where we inspect the #root element where this <Fragment> element is written:

Inspecting #root after having used a fragment.
Inspecting #root after having used a fragment.

See how there is no element surrounding the <h1> and <p>, all thanks to fragments.

Fragments are simple, quick, and amazing!

Moving on, if we don't want to directly access Fragment, we could rewrite the code as follows, using the fully-qualified form, React.Fragment:

import React from 'react';

function App() {
   return (
      <React.Fragment>
         <h1>A heading</h1>
         <p>A paragraph</p>
      </React.Fragment>
   );
}

However, this probably isn't that commonly used. In fact, even Fragment isn't used most of the times since there is a way simpler and cooler variant of representing a fragment in JSX.

That is to use <> and </>, without any text inside the tags themselves.

Keep in mind that there's no need to manually import Fragment when using the <>...</> syntax.

Henceforth, the code above could be identically represented as follows:

function App() {
   return (
      <>
         <h1>A heading</h1>
         <p>A paragraph</p>
      </>
   );
}

Live Example

Peaches and cream!

Using keys with fragments

An extremely vital point to note regarding fragments in React is that they can only accept a key prop, nothing else.

Not allowing any other prop makes perfect sense since fragments neither use their props (apart from key) for any purpose, nor pass them down to child elements.

On the other hand, specifying the key prop to fragments makes sense because fragments, just like user-defined components, show up in the internal tree of React elements and thus participate in the crucial reconciliation process.

Likewise, if we were to render a list of fragment elements, React would've thrown the same key warning to us unless we added a key prop to each fragment element.

And this could've only been possible if fragments were to entertain keys, which they do.

key can't be provided to <>...</>!

Be wary of the fact that if we wish to specify the key prop to a fragment, we can NOT use the shorter <>...</> syntax.

That is, the following is wrong:

<key={0}>...</>

The correct way is to refer to the Fragment component:

<Fragment key={0}>...</>

As one can reason, this behavior of JSX was implemented in order to keep the grammar of the language simple when using the terser <>...</> syntax.

After all, it's possible that <key={0}> might be trying to refer to a <key> element in an invalid way, right? "Simplify the grammar and forget about these worries" is what JSX says.