Why are Fragments in React 16 better than container divs?

Reactjs

Reactjs Problem Overview


In React 16.2, improved support for Fragments has been added. More information can be found on React's blog post https://reactjs.org/blog/2017/11/28/react-v16.2.0-fragment-support.html">here.</a>

We are all familiar with the following code:

render() {
  return (
    // Extraneous div element :(
    <div>
      Some text.
      <h2>A heading</h2>
      More text.
      <h2>Another heading</h2>
      Even more text.
    </div>
  );
}

Yes, we need a container div, but it's not that big of a deal.

In React 16.2, we can do this to avoid the surrounding container div:

render() {
  return (
    <Fragment>
      Some text.
      <h2>A heading</h2>
      More text.
      <h2>Another heading</h2>
      Even more text.
    </Fragment>
  );
}

In either case, we still need need a container element surround the inner elements.

My question is, why is using a Fragment preferable? Does it help with performance? If so, why? Would love some insight.

Reactjs Solutions


Solution 1 - Reactjs

  1. 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.
  2. 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.
  3. The DOM inspector is less cluttered. :-)

You can find the descriptions of some other use cases in this React issue: Add fragment API to allow returning multiple components from render

Solution 2 - Reactjs

Adding to all answers above there is one more advantage: code readability, Fragment component supports a syntactic sugar form, <>. Thus the code in your question can be written more easily as:

render() {
  return (
    <>
      Some text.
      <h2>A heading</h2>
      More text.
      <h2>Another heading</h2>
      Even more text.
    </>
  );
}

According to docs,

> In React, this desugars to a <React.Fragment/> element, as in the example from the previous section. (Non-React frameworks that use JSX may compile to something different.)

Clutter-free, right ?

Note that you still need to use <Fragment> syntax if you need to provide key to the fragment.

Solution 3 - Reactjs

  • Added features not possible before with JSX
  • Better semantic jsx markup. Wrapper elements are used when needed not because they are forced to.
  • Less overall dom markup (increased render performance and less memory overhead)

It as simple as when you don't need a wrapper element you aren't forced to use one. Having less elements is great but I think the biggest benefit is being able to render elements in jsx that weren't previously possible and adding better semantic meaning to wrapper elements because they are optional now.

This wasn't possible before:

 <select>
    {this.renderOptions()}
 </select>

Glancing at the following in React 15 you can't tell if the wrapper element is needed or not:

<span>
  <h1>Hello</h1>
  {this.getContent()}
</span>

Solution 4 - Reactjs

As per the reactjs.org docs most important needs of <Fragment> </Fragment> instead of div's are to avoid breaking HTML semantics. When we use div's instead of <Fragment> </Fragment> we break the HTML semantics.

To know more about html semantics. please click and also there are cases where if you use div's instead of Fragments it will be invalid html, for example look at this code:

class Columns extends React.Component {
  render() {
    return (
      <div>
        <td>Hello</td>
        <td>World</td>
      </div>
    );
  }
}
  
<table>
      <tr>
        <div>
          <td>Hello</td>
          <td>World</td>
        </div>
      </tr>
 </table>

Fragments solve this problem.

Solution 5 - Reactjs

When working with React, there are cases where you will need to render multiple elements or return a group of related items. Here’s an example:

function App() {
  return (
    <h1>Hello React!</h1>
    <h1>Hello React Again!</h1>
  );
}

If you try to run your app with the code above, you will run into an error stating that Adjacent JSX elements must be wrapped in an enclosing tag. This implies that you need to wrap both elements within a parent div.

function App() {
  return (
    <div>
      <h1>Hello React!</h1>
      <h1>Hello React Again!</h1>
    </div>
  );
}

Doing this will fix the error, but it comes with a degree of risk. You are adding an extra node to the DOM, which is not necessary. In a case like this, where the above is a child component that will be enclosed within a parent component, this becomes a problem.

function Table() {
  return (
    <table>
      <td>This is a Table Component</td>
      <Columns />
    </table>
  );
}

function Columns() {
  return (
    <div>
      <td>Hello React!</td>
      <td>Hello React Again!</td>
    </div>
  );
}

The resulting HTML for the Table component will be invalid because of the additional div that was added.

function Table() {
  return (
    <table>
      <td>This is a Table Component</td>
      <div>
        <td>Hello React!</td>
        <td>Hello React Again!</td>
      </div>      
    </table>
  );
}

Let’s take a look at a better way of solving this by using React Fragment, which will not add any additional node to the DOM. The syntax looks like this:

function Columns() {
  return (
    <React.Fragment>
      <td>Hello React!</td>
      <td>Hello React Again!</td>
    </React.Fragment>
  );
}

You can also use the short syntax <> for declaring a Fragment.

function Columns() {
  return (
    <>
      <td>Hello React!</td>
      <td>Hello React Again!</td>
    </>
  );
}

Solution 6 - Reactjs

  1. Using <React.Fragment>...</React.Fragment>, we can add a parent tag to our JSX elements without adding an extra node to the DOM.
  2. you can replace the extra div tags with React.Fragment
  3. writing React.Fragment every time is too long for you. React.Fragment has a shorthand syntax that you can use. It is <>...</>.

Solution 7 - Reactjs

When you want to group components but don't want a div tag HTML in the generated HTML, you can use fragment. The generated HTML for <> <p> Hello </p> </> is just this: <p> Hello </p>

If we'd have used div container, the <div>…</div> will be generated too!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMax MillingtonView Question on Stackoverflow
Solution 1 - ReactjsDan AbramovView Answer on Stackoverflow
Solution 2 - ReactjsDaneView Answer on Stackoverflow
Solution 3 - ReactjsplleeView Answer on Stackoverflow
Solution 4 - ReactjsSeeta Ram YadavView Answer on Stackoverflow
Solution 5 - ReactjsSourabh ChavanView Answer on Stackoverflow
Solution 6 - ReactjsHemantView Answer on Stackoverflow
Solution 7 - ReactjsVaishaliView Answer on Stackoverflow