Last update on Sunday, December 2nd 2018

Using Higher Order Components in a React application

If you followed the latest tutorials, you are aware that React can now be used with Ionic.
This technology comes with many new concepts and we will see one of them in this tutorial.
This tutorial is an introduction to Higher Order Components(HOC) and I do have another one more Ionic-oriented in the pipe.

The HOC pattern consists of creating reusable React Components that can be plugged around other React Components. They are also compared to Containers because just like a jar, once it's created we can reuse the same jar to put anything we want like water, rock, sand and if we want, we can swap containers to use a vase instead.

If you are not familiar with the React environnement, you must install the create-react-app tool:

npm i -g create-react-app 

Then create a new React project:

create-react-app my-app
cd my-app
npm start

Now we can start coding.

A simple red border

We will start with the App.js file:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import RedBorderedComponent from './Components/RedBorderedComponent';

class App extends Component {
  render() {
    return <RedBorderedComponent/>
  }
}

export default App;

Our aim is to create a simple RedBorderedComponent which looks like this:

import React, { Component } from 'react';

import BasicComponent from './BasicComponent';

class RedBorderedComponent extends Component {
  render() {
    return <BasicComponent />
  }
}

export default RedBorderedComponent;

For now, our React Component only displays the following BasicComponent:

import React, { Component } from 'react';

class BasicComponent extends Component {
  render() {
    return <span> Hi I'm a basic component,</span>
  }
}

export default BasicComponent;

That's it, just a React Component with a simple render method.
Now, how do we add a red border around this React Component without making any modification to the current files or some CSS targetting a specific id, class or element?

That's when our Wrapper Component comes to the rescue.

By using Higher Order Components (HOC), we can have a simple React Component and augment (or decorate) it with information. It can be data, CSS, anything we want!

The naming convention is to use "withXXX", so we will use withRedWrapper.
In your next projects you can name it withDataStorage, withGeolocationData or withSparksAroundTheCorners. Everything that can explain the contribution.

We now create a withRedWrapper.js file in a withRedWrapper folder:

import React from 'react';

export default function withRedWrapper(OriginalComponent) {
  class HOC extends React.Component {
    render() {
      return <div style={{border: "5px red solid"}}>
        <OriginalComponent />
        I got wrapped with a red border
      </div>;
    }
  }
  return HOC;
}

We are exporting a function named withRedWrapper.
This function receives an OriginalComponent which will be the BasicComponent in our example.

We then create an HOC Class that extends React.Component which allows us to declare the render method.
This method will return what we want to display, we start by opening a <div> which will wrap everything with a red border. We finally display the content from the OriginalComponent and add some text saying that it got wrapped with a red border.

Finally we modify the RedBorderedComponent.js file:

import withRedWrapper from '../withRedWrapper/withRedWrapper';
...

export default withRedWrapper(RedBorderedComponent);

We only need to import our withRedWrapper function and wrap the RedBorderedComponent.

And that's it, our React Component now has a red border.

React HOC red Wrapper result 1

We can even create the following component:

import React, { Component } from 'react';

class AnotherComponent extends Component {
  render() {
    return <span>I'm another Component, I don't want to interact with other Components but in the end, </span>
  }
}

export default AnotherComponent;

And use it:


class RedBorderedComponent extends Component {
  render() {
    return <AnotherComponent />
  }
}

Which gives:

React HOC red Wrapper result 2

This example was very simple, let's take a step further now.

Names Container

This part will be more business oriented.
We are going to create two React Components that display some names, they will both use the following withNames Component:

import React from 'react';

export default function withNames(OriginalComponent) {
  class HOC extends React.Component {
    render() {
      const names = ['Tim', 'Tam', 'Tom'];
      return <OriginalComponent {...this.props} names={names}/>
    }
  }
  return HOC;
}

We start by putting the names in a names array, in a real world scenario we generally make a call to a server to get this information, but let's keep it simple.

Like before we use the OriginalComponent that we received. However, this time we pass a new names props.
This is similar to the previous case, in this case we add more information on the Component itself instead of around.
We don't forget to propagate the props that were originally passed to the Component by using the {...this.props} trick.

This Container is now ready to be used by a NamesLineComponent in the NamesLineComponent.js file:

import React, { Component } from 'react';
import withNames from '../withNames/withNames';

class NamesLineComponent extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    return <span> {
      this.props.names.map(name => {
        return <span key={name}>{name}, </span>
        }
      )
    } </span>
  }
}

export default withNames(NamesLineComponent);

We import the withNames Container and loop on the names that we receive (or inhert) from the props to display them on the same line.

Which gives:

React HOC names line result 2

We do the same process for a NamesListComponent in the NamesListComponent.js file:

import React, { Component } from 'react';
import withNames from '../withNames/withNames';

class NamesListComponent extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    return <ul> {
      this.props.names.map(name => {
        return <li key={name}>{name}</li>
        }
      )
    } </ul>
  }
}

export default withNames(NamesListComponent);

This time we just display the information by using the <ul> <li> tags.

And we finally have:

React HOC names list result 2

Conclusion

Higher Order Components (HOC) are quite useful, it's quite common to have some components in an application that display the same information in a different way. With HOC we can create our React Components then quickly swap the Containers that we want to use in different area of an application.
There is only a simple implicit contract between the Components agreeing that some specific props will be received among the original ones.

Creating an Avengers app with the Ionic API, React and Redux

Creating an Avengers app with the Ionic API and React

How Parcel simplifies modern JavaScript projects

Stay up to date


Join over 4000 other developers who already receive my tutorials and their source code out of the oven + other free stuff!