loading...
Cover image for This is why you can't return adjacent JSX elements.

This is why you can't return adjacent JSX elements.

tusharkashyap63 profile image Tushar Kashyap ・3 min read

I am using React from quite some time now and it's an amazing tool to write maintainable applications pretty fast. But I remember when I started learning it, I was shown my first error by the instructor

Syntax error: Adjacent JSX elements must be wrapped in an enclosing tag

And he straightaway told that you can only return a single element from a component, if you have more than one just wrap them all in a parent element like a div or React.Fragment(which I came to know about later).

And I was like
pixel thumbs up unicorn
OKAY!!! I can remember that.

But to anyone who is starting with React, you don't have to do that.

P.S. Picture of a Unicorn being happy and agreeing(i.e. thumbs up). I wanted to tell this explicitly as the image can be a little pixelated. Pun Intended.

Understanding how React works

Let us see what is happening under the hood when you are writing JSX and easing through the development process.

JSX is just a syntactic sugar over the createElement method of the React library, but a sugar so sweet no one can avoid it(and no one should).
What this means is what you can do with JSX can be done with React.createElement()

Let's start by making a h1 element.

React.createElement("h1", { id: "myHeading" }, "Unicorn Party Here");

Let me break createElement to you, the first argument it takes defines the type of element we want to create. The second argument takes an object of element's properties and here we are giving it an id. The third argument are its children i.e. anything you would have put between the opening and closing tags like <h1>πŸ‘‰ children here</h1> in normal HTML.

This will make an actual h1 while rendering that looks like <h1 id="myHeading">Unicorn Party Here</h1>

How to add children elements to a parent element

Instinctively thinking from what we saw above, children elements can be added as follows

React.createElement(
  "ul",
  null,
  React.createElement("li", null, "Item one"),
  React.createElement("li", null, "Item two"),
  React.createElement("li", null, "Item three")
);

This will be rendered as

<ul>
  <li>Item one</li>
  <li>Item two</li>
  <li>Item three</li>
</ul>

We can see that any number of arguments after the second argument are taken as children arguments. This is what happens when you write JSX, it uses createElement and renders the DOM as shown in the examples.

The return statement

Now let's rethink what can we return from a function in JavaScript. With the obvious numbers, strings out of the way functions can return anything in between arrays, objects and even other function but lets look at some caveats with the return statement.

function square(a) {
  return
  a * a;
}

this will be converted to

function square(a) {
  return;
  a * a;
}

as the return statement is affected by automatic semicolon insertion, so no line breaks are allowed. Read more at MDN.

So we use parenthesis() to prevent return from adding automatic semicolon.

function square(a) {
  return (
    a * a;
  )
}

This will return the correct answer.

But looking at the next line you'll say, What Unicorn milk am I drinking πŸ€·β€β™€οΈπŸ€·β€β™‚οΈ?

function returnSelf(a, b) {
  return (
    a
    b
  )
}

This is simply wrong syntax

So when you try to return two adjacent JSX elements

return (
  <h1>Hello World</h1>
  <p>Are Unicorns even real?</p>
);

which is the same as

return (
  React.createElement("h1", null, "Hello World")
  React.createElement("p", null, "Are Unicorns even real?")
);

is also the same wrong syntax.

But wrapping it all in a div sounds like a perfect solution and it is

return (
  <div>
    <h1>Hello World</h1>
    <p>Are Unicorns even real?</p>
  </div>
);

which is the same as

return (
  React.createElement("div", {id: "container"}, 
    React.createElement("h1", null, "Hello World"),
    React.createElement("p", null, "Are Unicorns even real?")
  )
);

And this is perfectly valid syntax, I mean we are returning single values from the time we started coding. In fact anything that is valid would work, you can also try returning an array of elements like this.

import React from 'react';
import ReactDOM from 'react-dom';

function ReturnJSXArray() {
  return [<h1>The End</h1>, <h3>πŸ¦„πŸ¦„πŸ¦„πŸ¦„</h3>];
}

ReactDOM.render(<ReturnJSXArray />, document.getElementById('root'));

And React will actually render these.

Once you've read this, it seems very obvious that a wrapper is needed for adjacent JSX or you can even return arrays of JSX(which you should avoid) but being so hooked up in learning React we tend to forget the obvious.

Posted on by:

tusharkashyap63 profile

Tushar Kashyap

@tusharkashyap63

Preoccupied all the time with anything front-end.

Discussion

pic
Editor guide
 

I've had to use the <> </> a few times, and also returned elements inside arrays a few times too, after this adjacent JSX error came up. Finally I understood why is the way is it. Thanks for the nice article.

 

Glad I could help.

 

Nice explanation. I have also written a similar article some time back with additional details which you can check out here

 

I checked it out, good work.
Check out his article to see more about how React.createElement works.

 

Thank you so much!

 

You can always return

function returnSelf(a, b) {
  return [
    a,
    b
  ]
}
 

Yes I said we can return arrays

 

What if React could automatically add <>, </> around these adjacent JSX elements?

 

But your program will never reach that stage when React can do anything. Wrong syntax will break your program in the first place. Please abide by the rules of JavaScript as React is just JavaScript.

 

I mean, while compiling, can’t React intelligently figure it out and add a parent block? I know it doesn’t do that now but it is quite possible isn’t it?

[deleted]

That is asking too much πŸ˜…

React is just a library.

 
 

Thank you so much :)

 

Great post and explanation !!

 

Thank you, Paras :)

 

You get that error because you can only return one thing at any given time. That error translates to "do something so you will only return one thing".

 

I know it asks you to return one element. In this article I'm trying to explain WHY does it want you to return one element.