React Fragments - What, Why, How
React Fragments were introduced in React 16.2.0. Even though they have been around for a while now, many React developers I have talked to haven't started to use them yet and the number one reason for this usually is that they have heard of them but haven't got around to learn about them.
So what are they and should you start using them? The answer to the latter is YES and the answer for the first question is what this blog post is going to tell you.
Are you new to React? Be sure to read my post 6 Things Every Beginner React Developer Should Know.
Problem
As the React.js docs state, a common pattern in React is for components to return multiple elements. Usually these elements are wrapped for example inside a div. In most cases the wrapper div is "irrelevant" and is only added because React components require you to return only one element. This kind of behaviour results in useless markup and sometimes even invalid HTML to be rendered, which is bad.
For example we could have a component Table
that renders an HTML table and inside that table the columns are rendered with another component called Columns
. It would probably look something like this.
1class Table extends React.Component {
2 render() {
3 return (
4 <table>
5 <tr>
6 <Columns />
7 </tr>
8 </table>
9 );
10 }
11}
12
13class Columns extends React.Component {
14 render() {
15 return (
16 <div>
17 <td>Hello</td>
18 <td>World</td>
19 </div>
20 );
21 }
22}
This would result in an invalid HTML to be rendered because the wrapper div from Columns
component is rendered inside the <tr>
.
1<table>
2 <tr>
3 <div>
4 <td>Hello</td>
5 <td>World</td>
6 </div>
7 </tr>
8</table>
Solution
Solution for this is, you guessed it, fragments! React fragments let you group a list of children without adding extra nodes to the DOM because fragments are not rendered to the DOM. So basically we use React.Fragment where we would normally use a wrapper div.
We can make use of fragments with <React.Fragments>
syntax. So we could write the Columns
component as follows.
1class Columns extends React.Component {
2 render() {
3 return (
4 <React.Fragment>
5 <td>Hello</td>
6 <td>World</td>
7 </React.Fragment>
8 );
9 }
10}
Now the Table component would render following HTML.
1<table>
2 <tr>
3 <td>Hello</td>
4 <td>World</td>
5 </tr>
6</table>
Fragments can also be declared with a short syntax which looks like an empty tag. Here is an example.
1class Columns extends React.Component {
2 render() {
3 return (
4 <>
5 <td>Hello</td>
6 <td>World</td>
7 </>
8 );
9 }
10}
Typical use cases
Return multiple elements
Most common use case for React fragments is probably when you need to return multiple elements. With fragments this is easy and you don't need your typical wrapper div for the elements.
1class Application extends React.Component {
2 render() {
3 return (
4 <React.Fragment>
5 <Header />
6 <Content />
7 <Footer />
8 </React.Fragment>
9 );
10 }
11}
Conditional rendering
React fragments can also be used when conditionally rendering elements. They make rendering groups of elements a lot easier without adding extra markup.
1class LoginForm extends React.Component {
2 render() {
3 return (
4 <form>
5 {this.props.isLoggedIn ? (
6 <React.Fragment>
7 <h3>Welcome</h3>
8 <p>You are logged in!</p>
9 </React.Fragment>
10 ) : (
11 <React.Fragment>
12 <h3>Login</h3>
13 <label for="username">Username</label>
14 <br />
15 <input type="text" id="username" />
16 <br />
17 <label for="password">Password</label>
18 <br />
19 <input type="password" id="password" />
20 <br />
21 <input type="submit" value="Login" />
22 </React.Fragment>
23 )}
24 </form>
25 );
26 }
27}
Arrays
Fragments can also help us when rendering arrays, because fragments can have key props! Let's say you have an array of user objects and you want to render all users from the array. You need to set key prop for every user so you would need to use element like div to wrap the user info. But because fragments can have key prop, you can instead use fragments and give the key prop for them and thus you don't need to introduce any extra markup.
1class UserList extends React.Component {
2 users = [
3 {
4 id: 1,
5 name: "Jack Bauer",
6 email: "jack.bauer@ctu.gov",
7 phone: "+358509283928",
8 },
9 {
10 id: 2,
11 name: "Tony Almeida",
12 email: "tony.almeida@ctu.gov",
13 phone: "+358508829378",
14 },
15 {
16 id: 3,
17 name: "Chloe O'brian",
18 email: "chloe.obrian@ctu.gov",
19 phone: "+358508899012",
20 },
21 ];
22
23 render() {
24 return (
25 <React.Fragment>
26 {this.users.map((user) => (
27 <React.Fragment key={user.id}>
28 <h2>{user.name}</h2>
29 <p>{user.email}</p>
30 <p>{user.phone}</p>
31 </React.Fragment>
32 ))}
33 </React.Fragment>
34 );
35 }
36}
Should I use fragments?
So are fragments worth using instead of say a wrapper div?
Dan Abramov answered this question on StackOverflow:
- It’s a tiny bit faster and has less memory usage (no need to create an extra DOM node). This only has a real benefit on very large and/or deep trees, but application performance often suffers from death by a thousand cuts. This is one cut less.
- Some CSS mechanisms like Flexbox and CSS Grid have a special parent-child relationship, and adding divs in the middle makes it hard to keep the desired layout while extracting logical components.
- The DOM inspector is less cluttered. :-)
So the fact that fragments eliminate the wrapper div which can cause problems with invalid HTML and with styling of the components plus the fact that they are faster and the DOM is less cluttered, I'd say they are worth using.
Wrapping up
What do you think about React fragments and are you using them in your own projects? Please leave a comment below, I would love to hear from you!
Also remember to subscribe to CodePulse newsletter, to stay tuned on the latest news and posts about modern web development. I also share exclusive tips and tricks for the newsletter subscribers!