Why Can't You Return Multiple Elements in React?
Every React dev has come across an error that looks something like this:
Adjacent JSX elements must be wrapped in an enclosing tag
React relies on a tree-like structure where nodes in the tree always have a root node.
The problem is if your component returns a list of elements then there is no "root node" and the React gods will throw errors at you.
Here's an example that could cause this error:
render() {
return (
<h1>I ❤️ code</h1>
<p>But why does it not work?</p>
<button>Give up</button>
);
}
Notice that our return statement is attempting to return 3 elements and there is no "root node".
Show me how to fix it already!
Luckily, there is an easy fix. If you have a list of elements and you need to return them, you can wrap them in an extra element, like a <div>
. This will satisfy React's 'root node' requirement.
This could look like this:
render() {
return (
<div>
<h1>I ❤️ code</h1>
<p>Especially when it works!</p>
<button>Win</button>
</div>
);
}
By wrapping our code in an extra div
, we are now returning one root node that contains the content we want to render.
But wait, there's more!
There's a better fix though. From React 16, we can create placeholder nodes called Fragments. You can read the official documentation on Fragments here: https://reactjs.org/docs/fragments.html.
The solution above works, but it will render the extra div around your list of DOM elements. It adds extra content to the DOM that isn't needed.
Fragments allow you to wrap your list of elements in a root node, without adding extra elements to the DOM.
Our solution with Fragments would look like this:
render() {
return (
<React.Fragment>
<h1>I ❤️ code</h1>
<p>Especially when it works!</p>
<button>Win</button>
</React.Fragment>
);
}
Fragments are a better choice here because the actual HTML output will only be the content we intended.
It won't wrap the extra div
that we needed to meet the "root node" requirement.
Shorthand Fragments
Fragments also have a shorthand version of their syntax for other lazy developers like me.
You can use empty brackets like so:
render() {
return (
<>
<h1>I ❤️ code</h1>
<p>Especially when it works!</p>
<button>Win</button>
</>
);
}
Less typing, and it makes a little more sense since they don't output any HTML anyway!