And you think to yourself: "Oh God, what have I done wrong again?"
But luckily for you (and for all of us - React developers), this time the problem is super simple.
Let's take a look at the code that caused the problem.
import React from "react";
const Fragment = () => {
return
<div>Fragments</div>
<p>in React</p>
;
};
export default Fragment;
As you can see, we are trying to return two JSX elements from our Fragment component.
And, as you probably understand, this is the root of our problem.
So, why?
Isn't it a common situation when you need to return multiple elements from a component?
And you are right - this is a common pattern in React.
But you have to remember:
Component must return only one parent element and not more, not less.
What can we do about this?
So, one solution is to wrap it in a "div" element.
Let's take a look at whether it works or not!
import React from "react";
const Fragment = () => {
return (
<div className="wrapper">
<p>Fragments</p>
<p>in React</p>
</div>
);
};
export default Fragment;
Hooray! It worked!
But is this the best solution?
Nah!
There are several problems that come with it.
First of all, we add an extra node to our DOM. It takes extra space in memory.
Secondly, it's just irrelevant. We need it only for our JSX to work. Kind of ridiculous, right?
And in addition to that, sometimes this div wrapper can even break our layout and lead to invalid HTML to be rendered!
You probably think, how this innocent div can break your HTML?
Let me show you a quick example that will demonstrate that!
Let's imagine that we wanna display a table.
So we define "table", "tbody", "tr" elements.
import Fragment from "./fragment";
function App() {
return (
<div className="App">
<table>
<tbody>
<tr>
<Fragment />
</tr>
</tbody>
</table>
</div>
);
}
export default App
And let's say, we want a separate component for our data cells ("td" elements).
import React from "react";
const Fragment = () => {
return (
<div className="wrapper">
<td>Team </td>
<td>Points</td>
<td> Wins</td>
</div>
);
};
export default Fragment;
We already know that we cannot return multiple values from a component.
Thus we will wrap our "td" elements in a div with class "wrapper" (no styles applied to this class, just for demonstration purposes)
Now let's check if it works or not!
Seems like it works but damn...
Look at the console ...
We cannot place "td" inside of a div.
And "tr" cannot contain the div element.
Q.E.D.
So, what should we do instead?
You guessed it right - we can use Fragments!
A fragment is just a syntax that allows you to group a list of children (as our div did) but...
Super important, Fragment does not add an extra node to the DOM.
Okay, that sounds like a win-win, right?
How to use it?
Pretty easy !
import React from "react";
const Fragment = () => {
return (
<React.Fragment>
<p>Fragments</p>
<p>in React</p>
</React.Fragment>
);
};
export default Fragment;
All we have to do is use React.Fragment instead of div.
Also, I need to mention that there is another form of React Fragment - short syntax that looks like an empty tag.
import React from "react";
const Fragment = () => {
return (
<>
<p>Fragments</p>
<p>in React</p>
</>
);
};
export default Fragment;
Both of these code examples will result in such DOM:
As you can see no additional JSX elements have been added to the DOM!
Is there any difference between React.Fragment and the short syntax?
Actually, there is one small difference
Look at this code snippet:
import React from "react";
const Fragment = () => {
const arrayOfNumbers = [1, 2, 3, 4, 5];
return arrayOfNumbers.map((number, index) => (
<>
<p>{number}</p>
<p>{index}</p>
</>
));
};
export default Fragment;
We iterate through the array and for each element return 2 paragraphs (value itself and its index).
We put these paragraphs in an empty tag (short syntax of React.Fragment)
Everything works fine but ...
We got this error in the console ...
If you read my previous post about React keys, you know what it's all about and how to deal with it.
If not, check it out!
So, as you understand, we have to add the key to our parent element.
And here is the problem.
We cannot do that with the short syntax of React.Fragment.
Instead, we have to use React.Fragment and give it a key attribute.
import React from "react";
const Fragment = () => {
const arrayOfNumbers = [1, 2, 3, 4, 5];
return arrayOfNumbers.map((number, index) => (
<React.Fragment key={index}>
<p>{number}</p>
<p>{index}</p>
</React.Fragment>
));
};
export default Fragment;
Brief conclusion:
Fragments can be used whenever you need to return multiple JSX elements from the component.
You should be using them instead of wrapping everything in a div because React.Fragment does not add an extra node to the DOM. There are 2 forms of it: full and short syntax.
The only difference between them is that you cannot use key attribute (if you need one) with short syntax.
And that's it, guys.
I hope that you have learned something new today!
I would appreciate it if you could like this post or leave a comment below!
Also, feel free to follow me on GitHub and Medium!
Adios, mi amigos)
Top comments (2)
Wow, thanks for this 👏🏽
I hope you liked it )