Aux Component vs React Fragment - which one is better?

Olena Drugalya - Nov 11 '20 - - Dev Community

In this blog post we are going to explore how to return multiple elements from a component's render(for class-based) or return (for functional) methods.

What elements are returned?

Let's refresh in the memory what elements are returned - those are React elements, which have been converted from HTML tags by JSX (JavaScript XML). JSX allows us to write HTML elements in JavaScript and place them in the DOM without any createElement() and/or appendChild() methods.
Example:

return() {
 <div>
  <h1>Hello World!</h1>
 </div>
}
Enter fullscreen mode Exit fullscreen mode

But we also know that "under the hood" there is Babel compiler, which transforms JSX into React.createElement() function:

return() {
 React.createElement('div', {}, [
  React.createElement('h1', {}, 'Hello World!')
]);
}
Enter fullscreen mode Exit fullscreen mode

So, as you can see, React.createElement can accept only one type of element (in our case it's div and h1) as first parameter. That is why when you return JSX from a function or statement, you must return a single element (with children or without).

In our example it is div which is single or top element for JSX.

Multiple elements

What if we want to return multiple elements and we don't need that div container?

Let's explore the following example:

const Table = () => {
    return (
      <table>
        <tr>
          <Columns />
        </tr>
      </table>
    );
}
Enter fullscreen mode Exit fullscreen mode

The component <Columns />in its turn is rendering a couple of columns:

const Columns = () => {
    return (
      <div>
        <td>Column 1</td>
        <td>Column 2</td>
      </div>
    );
  }
Enter fullscreen mode Exit fullscreen mode

As a result of the code above, we are getting invalid HTML from <Table /> component on the page:

<table>
  <tr>
    <div>
      <td>Column 1</td>
      <td>Column 2</td>
    </div>
  </tr>
</table>
Enter fullscreen mode Exit fullscreen mode

Solution?

This problem can be solved in 2 ways:
1./ By using Aux Component (Auxiliary) or HOC
2./ By using React.Fragment component

Let's examine both of ways.

Aux (Auxiliary) Components or HOC

A higher-order component (HOC) in React is a pattern used to share common functionality between components without repeating code. HOC is actually not a component though, it is a function. A HOC function takes a component as an argument and returns a component. It transforms a component into another component and adds additional data or functionality.

In short:

const NewComponent = (BaseComponent) => {
  // ... create new component from old one and update
  return UpdatedComponent
}
Enter fullscreen mode Exit fullscreen mode

HOC can be used as a container for another component (in this case it's often called auxiliary component or Aux in the project). In this case it simply takes props as argument and returns children:

const Aux = (props) => props.children;
export default Aux;
Enter fullscreen mode Exit fullscreen mode

In our example we can simply change wrapper div with Aux:

const Columns = () => {
    return (
      <Aux>
        <td>Column 1</td>
        <td>Column 2</td>
      </Aux>
    );
  }
Enter fullscreen mode Exit fullscreen mode

And problem solved!

React.Fragment

React.Fragment was introduced in React 16.2.0.
React.Fragment 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.

In our example we can simply change wrapper div with React.Fragment:

const Columns = () => {
    return (
      <React.Fragment>
        <td>Column 1</td>
        <td>Column 2</td>
      </React.Fragment>
    );
  }
Enter fullscreen mode Exit fullscreen mode

OR fragments can also be declared with a short syntax which looks like an empty tag:

const Columns = () => {
    return (
      <>
        <td>Column 1</td>
        <td>Column 2</td>
      </>
    );
  }
Enter fullscreen mode Exit fullscreen mode

And problem solved!

Conclusion:

  • It's possible to use both variants since they do the same job - allow to return multiple JSX elements without adding extra layer
  • Using React.Fragment has more benefits though, since you don't need to create extra component and it’s a tiny bit faster and has less memory usage (no need to create an extra DOM node).

Thank you for reading my blog and thank you for your comments :)

Buy Me a Coffee at ko-fi.com

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .