What are Higher-Order Components in React?
Tags: react, tutorial, javascript
Published: 2021-08-12 06:08:36

_by author [Queen Nnakwue]()_

If you’ve ever considered it repetitive and cumbersome writing the same logic or having to fetch data in different components, then this article is for you. These problems are some of the basic challenges faced by React developers but can be solved using higher-order components. 

One key use of HOC is that it allows you to abstract out the common functionalities of a component and build a function. With HOC, you can share logic across different components without having to rewrite it. HOC amplifies one of the best-known principles of programming called the don’t-repeat-yourself (DRY) principle, a very important principle to adhere to generally when writing code or building an application.

In this tutorial, we will start by looking at Higher-Order Components in React from a high level- what they are, why you should use them, and how to write yours. We will also cover different use cases with real-life examples alongside a few caveats or a few things to avoid when using higher-order components.


## **What is Higher-Order Component- HOC?**

Higher-Order Component in React is a function that takes a component as an argument and returns a new component. It is the state-of-the-art technique in React for reusing component logic. The HOC adds additional data or functionality to an original component. These components are not part of the React API, but a pattern that comes to the fore from React’s compositional nature. In simple code it looks something like this:

```javascript
const NewComponent = higherOrderComponent(originalComponent)
```


Here, the function called `higherOrderComponent` that takes an argument- `originalComponent`. `higherOrderComponent` is a HOC component that adds some additional functionality to `originalComponent` and returns a new component. In addition, the `NewComponent` can also be referred to as `EnhancedComponent` like so:

```javascript
const EnhancedComponent = higherOrderComponent(originalComponent)
```

Here’s HOC in simple terms:


1. It is a component
2. It takes two arguments. The first argument is a component in which we want to add logic, and the second argument is data
3. Then it returns a new component
4. The returned component is the enhanced version of the component that we have passed.

Quite easy right? Now, let us dive into some facts about higher-order components and a basic example.


## **Facts about HOCs**
- One of the powers of the HOC pattern is that you can build up a simple functional component with whatever logic you want
- You can update/edit or transform props outside of your present component
- Just like JavaScript functions, HOCs can be pure functions that return a new component
- With HOCs, components are not mutated or modified. Instead, components are created.
- HOC is used to compose components for code reusability.

## **Example**

Let’s see the simplest form of a higher-order component. Consider this example-


```javascript
import React from 'react';

const updatedComponent = OriginalComponent => {
  class NewComponent extends React.Component {
    render() {
      return <OriginalComponent />
    }
  }
  return NewComponent
}
```


Here, we created an arrow function that accepts the `OriginalComponent` as its parameter while also returning a new component called `NewComponent`. Thereafter, we returned the `OriginalComponent` inside our `render` method and finally returned the `NewComponent` inside the arrow function. 

As seen from our code snippet above, a HOC is a function- `UpdatedComponent`  that accepts the original component- `OriginalComponent` and returns a new or enhanced component- `NewComponent`. This is the most basic example of a Higher Order Component 

## Open Source Session Replay
Debugging a web application in production may be challenging and time-consuming. [OpenReplay](https://github.com/openreplay/openreplay) is an Open-source alternative to FullStory, LogRocket and Hotjar. It allows you to monitor and replay everything your users do and shows how your app behaves for every issue. 
It’s like having your browser’s inspector open while looking over your user’s shoulder.
OpenReplay is the only open-source alternative currently available.

![OpenReplay](https://raw.githubusercontent.com/openreplay/openreplay/main/static/replayer.png)

Happy debugging, for modern frontend teams - [Start monitoring your web app for free](https://github.com/openreplay/openreplay).

## **Use Cases**

In this paragraph, we will discuss the different ways higher-order functions can be used. One of such include:


- **To conditionally render components:**
    HOCs can be used to conditionally render components. For instance, there might be a case with many components, when they are to be shown if a particular criterion is met with the info that's provided in their props. Since HOCs have access to the wrapped component props, we will have a reusable HOC that conditionally renders the component depending on the info provided.


- **Managing common user-interaction states**
    Another use-case of HOC is that it can be used to manage common user-interaction states. It is common knowledge that users feel pampered when our application controls respond to something as small as their cursor movements. For example, a user-interaction state like the hover and focus effect is often displayed beautifully, without repeated handlers with each component, by abstracting to a HOC which may have an occasion hook to reinforce the wrapped component with a state-specific flag.


- **Providing components with specific styles**
    HOCs can also be used to provide components with specific styles. From the foregoing (managing common user-interaction states), based on the flag that we get from the HOC, we may have flag-specific styles not just for user interaction states, but also data-specific ones. In addition, we can also have some more trivial styles like background color, font size, font-weight at multiple places if the need arises. These styles can be easily provided through a Higher Order Component by wrapping the component with one, that just augments props with the precise className(s).


- **Provide a component with just any prop**
    This is **a well-liked** use case for HOCs. With HOCs, we can study our codebase and decipher what reusable prop is required across components. Then, we will have a wrapper HOC to supply those components with the reusable prop.


## Building A Higher-Order Component

In this section, we are going to build our first higher-order component. Also, we are going to showcase the usefulness of the higher-order component. So we are going to be creating three `Counters`: `CounterA`, `CounterB`, and `CounterC` that will render a button and each of these buttons are going to have a corresponding counter within it, handled by its state. The idea is that whenever we click on each of the buttons, each of the `Counter` is going to increment. 

All three component is going to have the same shared code and we are going to use a higher-order component to extract the common logic to make it a lot more simple in general.

Sounds interesting? Let’s get started:

On your IDE, create a folder and inside the folder, open your terminal and create a new react app using `npx create-react-app` . Inside of your `src` folder, create a `component`  folder to house our three components. Inside the `component` folder, create three files called `CounterA`, `CounterB`, and `CounterC` like so:


![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ve951zqopbqj18kgn8ys.png)


Now let’s go ahead and write some code. In `CounterA`, let’s import React and create a class component called `CounterA`. Let’s call the `render` method and return a `button`  which we will call `CounterA` and finally, let’s export our class component, `CounterA`. 

Your `CounterA.js` fil should look like so:


```javascript
import React from 'react';
class CounterA extends React.Component {
    constructor(props) {
        super(props)
    }
    render() {
        return (
            <button>CounterA :</button>
        )
    }
}
export default CounterA;
```


Since the plan is to create three components with similar logic so we can use higher-order component to extract the common logic, let’s go ahead and replicate our code in `CounterA` inside both `CounterB` and `CounterC`. 

Please refer to [this repo](https://github.com/QNNAKWUE/higher-order-components/blob/CounterA-B-1115550/src/components/CounterB.js) for code snippets for our `CounterB` component and [this repo](https://github.com/QNNAKWUE/higher-order-components/blob/main/src/components/CounterC.js) for `CounterC`.

To see what our code looks like on the browser, let’s run `npm start` on our terminal to start our application. You should get something similar to this on your browser:


![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4ieh4c07umcutodjjsiu.png)


Next, let’s go ahead and implement some functionalities to our code in terms of clicking on the button and incrementing the `count` of each one. To start with, let’s define our `state` like so:


```javascript
import React from 'react';
class CounterA extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            count : 0
        }
    }
    CountIncrement = () => {
        this.state.count++;
        this.setState({count: this.state.count});
    }
    render() {
        return (
            <button onClick={this.CountIncrement}>CounterA :{this.state.count} </button>
        )
    }
}
export default CounterA;
```



1. We initialized our `state` inside our constructor and set `count` to `0`
2. We created a method called `CountIncrement`, incremented our `count` value using the increment method, and then we set our state to the new incremented value (still inside our `CountIncrement` method).
3. Inside the `render` method, we called the `onClick` event listener on our `button`, then we render our `state`- `this.state.count`.

Go back to your browser and reload your page. Notice that on click of `CounterA`, there is an increase in its value!. Next, let’s update our `CounterB` and `CounterC` components with the code in `CounterA`. You should have the same code in all three components because they are all doing the same thing.

Obviously, there is a duplicity in logic in all three components. For example, there’s an increase count method in all three and the state is keeping track of the count in all three as well. This is where HOC comes in handy. To prevent a repetition of these sorts, we are going to extract the common logic in all three components using a **higher-order component,** such that we can reuse them (the common logic) when we need them.

Let’s take a look at how to actually implement a higher-order component. To begin, let’s create a file called `Wrapper.js` inside our `src` folder which will house our HOC. So, let’s begin:


```javascript
import React from `react`;
const Wrapper = WrappedComponent => {
    class Wrapper extends React.Component {
        constructor(props){
            super(props)
            this.state = {
                count: 0
            }
        }
        CountIncrement = () => {
        this.state.count++;
        this.setState({count: this.state.count});
    }
        render () {
            return (
                <WrappedComponent
                    count={this.state.count}
                    CountIncrement={this.CountIncrement}

                />
            )
        }
    }
    return Wrapper;
}
export default Wrapper;
```



1. We imported React as usual
2. We created a stateless functional component which we called `Wrapper.js` which takes an argument called `WrappedComponent`
3. Inside our `Wrapper.js`, we created a react stateful component called `Wrapper.js`, called the `constructor` function and `super` where we passed `props` as a parameter
4. We then called `this.state={count : 0}` which we implemented in all three components. Note: this is where the abstraction comes into place
5. Next, we called our `render` function and we rendered/returned the `WrappedComponent` which we gave some props: `count` and `CountIncrement` which we defined in lines `11-13`
6. At the end of the component, we returned our `Wrapper.js` component

This is essentially how you implement your higher-order component. Next, we are going to see how to utilize it.

Go back to your `CounterA.js` file and import our HOC using the syntax below:


```javascript
import Wrapper from '../Wrapper';
```

In our `CounterA.js`, delete your state component and method because both are now being handled by our HOC- `Wrapper.js`. Let’s convert our `CounterA.js` into a stateless component and return the `button`. Also, delete the `this`  keyword like so:


```javascript
import React from 'react';
import Wrapper from '../Wrapper';
const CounterA = () => {
      return (
            <button onClick={CountIncrement}>CounterA :{count} </button>
        )
}

export default CounterA;
```


Wondering at this point how we are going to access those variables? We can access the variables from the props in `CounterA` and we can get those props by passing `CounterA` into our HOC component which is `Wrapper.js`. Also, we can go ahead and use `object destructuring` in JavaScript to get both the `CountIncrement` and the `count` from the state component.  

Our `CounterA.js` file should now look like this:


```javascript
import React from 'react';
import Wrapper from '../Wrapper';
const CounterA = (props) => {
       const {CountIncrement, count} = props; //getting those variables we were missing before
      return (
            <button onClick={CountIncrement}>CounterA :{count} </button>
        )
}

export default Wrapper(CounterA);
```


Now, let’s rerun our code to see if our `CounterA` still increments on click of the button.

Viola! It still does. Super amazing!!!

So, we have successfully used higher-order components in our `CounterA.js` file to get rid of a lot of code that we didn’t need - functionalities such as the method we are using and the state we are keeping track of. 

Kindly refer to the [Github repo](https://github.com/QNNAKWUE/higher-order-components/blob/main/src/App.js) to see how your `CounterB` and `CounterC` component should look like.

## **Things to avoid when using Higher-order component**

As with many concepts in programming, there are certain things to avoid when using HOC. A few of these caveats include:


- **Avoid using HOCs inside the render method**
    In React, component identity should be consistent across renders. This is because React’s reconciliation process uses component identity to decide whether it should update the prevailing subtree or mount a replacement between two renders. 
    For example, using HOCs inside the render method cannot preserve the identity of HOCs across render and this invariably affects the overall app performance.
    Also, when a component’s state changes, React has got to calculate if it's necessary to update the DOM. It does this by creating a virtual DOM and comparing it with the present DOM. during this context, the virtual DOM will contain the new state of the component.
    As a best practice, we should apply HOCs outside the component definition so that the resulting component is created only once.


- **Refs are not passed through**
    While you may want to pass all props to the wrapped component, you should pay particular attention to refs since they're not really props. Refs are handled specially in React like `key`. For instance,  If you add a ref to an element whose component is the result of a HOC, the ref refers to an instance of the outermost container component, not the wrapped component.
    To solve this problem, use the `React.forwardRef` API.


## **Conclusion**

In a nutshell, higher-order components are useful and important because they extract code away from components that are using the same code. So, it is essentially solving the problem of repetitiveness in our code.
 
In this tutorial, we have looked at higher-order components and how we can use them in our code with real-world examples. We also covered use cases of higher-order components, facts, and of course some caveat/things to avoid when using higher-order components.


## **Github link**

Please see below a link to the code examples on Github:

- [Github repo](https://github.com/QNNAKWUE/higher-order-components)


## **Further resources**

Refer to the [React documentation](https://reactjs.org/docs/higher-order-components.html) if you want to dive deeper into some of the things we discussed above.