Alexandre Gomes

Full-Stack Web and ÐApps Developer

React 16: Fragments, or how to avoid unnecessary DOM nodes

"Adjacent JSX elements must be wrapped in an enclosing tag"

How many of us React developers have seen this message over the course of our usage ? An usual pattern in react components is to render multiple JSX elements, such as

import React from 'react';

const MyAmazingComponent = () => (
  <CoolComponent />
  <AnotherCoolComponent />
);

export default MyAmazingComponent;

Unfortunately, due to the way react works, this is not possible, we have to wrap it in a tag, so most of the time we just wrap it in a div, this way :

import React from 'react';

const MyAmazingComponent = () => (
  <div> // Unnecessary div
    <CoolComponent />
    <AnotherCoolComponent />
  </div>
);

export default MyAmazingComponent;

While it might not seem like a big of a deal at first, this has two consequences :

  1. Adding unnecessary DOM nodes
  2. Making certain third-party component libraries more difficult to use, unless we tweak our components architecture a little bit

React 16 brought a new feature called Fragments. Essentially, it allows you to wrap adjacent JSX elements without the use of a wrapping tag. When parsed to the virtual DOM, there won't be anything wrapping your elements. So, our code will look as such now :

import React from 'react';
const MyAmazingComponent = () => (
  <React.Fragment> // Happy virtual DOM :) 
    <CoolComponent />
    <AnotherCoolComponent />
  </React.Fragment>
);

export default MyAmazingComponent;

or if using destructuring to import react :

import React, { Fragment } from 'react';

const MyAmazingComponent = () => (
  <Fragment>  
    <CoolComponent />
    <AnotherCoolComponent />
  </Fragment>
);

export default MyAmazingComponent;

In addition to the added benefits of not having DOM nodes that we wouldn't need, there is also the fact that it is clear Fragment serves as a (virtual, not parsed) wrapper for adjacent elements, whereas with the usual div wrapping, other developers looking at your component might think there is a use for that div you added.

Amazing, isn't it ? Well, there is more, we even have a shorthand available :

import React from 'react';

const MyAmazingComponent = () => (
  <>  
    <CoolComponent />
    <AnotherCoolComponent />
  </>
);

export default MyAmazingComponent;

As usual, thanks to the React team for making our development experience better every release !