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 React.createElement() call, 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

Another solution is to use Fragment, a relatively new React feature that solves the problem for us:

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

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.

Remember to import it from React first:

import React, { Fragment } from 'react'

There’s also a shorthand syntax, an empty tag:

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

It does the same thing. The only difference is that the shorthand can’t take any attributes, so if you need to pass a key (for example inside a loop), you have to use the full <Fragment> form.

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
~~~

Related posts about react: