How to return multiple elements in JSX

By

Learn how to return multiple elements from a React component in JSX, working around the single-parent rule with a wrapper div, an array, or a Fragment.

~~~

When writing JSX in React, there’s one caveat: you must return one parent item. Not more than one. To return multiple elements, you wrap them in a container element, return them as an array, or use a Fragment.

For example, this is not possible:

const Pets = () => {
  return (
    <Dog />
    <Cat />
  )
}

Why does this rule exist?

JSX looks like HTML, but it compiles to plain JavaScript function calls. Each element becomes a function call (React.createElement() with the classic setup, jsx() from react/jsx-runtime with the automatic runtime modern tooling uses), and a function can only return one value.

Two sibling elements would mean returning two values at once, which JavaScript can’t do. That’s why React forces a single parent.

Wrap everything in a div

One “classic” way to solve this is to wrap components and other HTML elements in a div:

const Pets = () => {
  return (
    <div>
      <Dog />
      <Cat />
    </div>
  )
}

However this introduces a problem: there’s an HTML element that was introduced just to make our JSX work. It’s not necessary in the resulting HTML, but that’s where it ends up.

Extra wrapper divs are not always harmless. They can break CSS layouts that rely on a direct parent-child relationship, like flexbox or grid containers.

Return an array

One solution is to return an array of JSX elements:

const Pets = () => {
  return [
    <Dog />,
    <Cat />
  ]
}

Notice the commas. Inside an array, elements are separated like any other array items.

Be careful with this approach: React treats the array like a list, so it warns you in the console that each child should have a unique key prop. To silence the warning you’d add a key to each element, which is annoying for elements that aren’t really a list.

Use a Fragment

The usual fix is a Fragment. Fragments arrived in React 16.2, back in 2017, and they work the same way in React 19.

With the automatic JSX runtime you do not need to import React just to use the short syntax:

const Pets = () => {
  return (
    <>
      <Dog />
      <Cat />
    </>
  )
}

It works like the div element we added before, but it’s not going to appear in the resulting HTML rendered to the browser. Win-win.

If you need attributes on the Fragment, for example a key inside a loop, use the named form:

import { Fragment } from 'react'

const Pets = ({ items }) => {
  return items.map((item) => (
    <Fragment key={item.id}>
      <Dog name={item.dog} />
      <Cat name={item.cat} />
    </Fragment>
  ))
}

The empty <>…</> tag can’t take a key, so a loop is the one case where you import Fragment by name.

My advice is to use a Fragment by default, and only reach for a wrapper div when you actually need an element in the page, for example to attach a CSS class.

Tagged: React · All topics

Want me to talk about your product? You can sponsor this site.

~~~

Related posts about react: