DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for React Higher Order Component
Puja Kundu
Puja Kundu

Posted on

React Higher Order Component

What is a Higher Order Component in React?

Higher order component is a function that takes a component as a parameter and returns an enhanced or changed component. Higher Order Component (HOC) adds additional data or functionality to the original component and returns an enhanced version of it.
A HOC does not modify the original component. It takes the original component and wraps it in a container component. The wrapped component receives data and returns output according to the received data. A HOC is a pure function.

Why use a Higher Order Component?

  • HOC is used to share common functionalities between components

  • It helps to reduce code duplication

  • Makes code manageable

Example

Let’s make a simple React application that will count the number of times you click on a button and hover on a text.

  • In your React app, create a folder named HOC. Inside the HOC folder, we will create a new file named β€˜withCounter.js’. β€˜withCounter.js’ is a Higher Order Component. β€˜withCounter.js’ will contain the logic we need to build the counter system.

  • Now, create another folder named β€˜components’. Inside this folder create a component named ClickCounter.js.

import React from "react";

class ClickCounter extends React.Component {

  render() {

    return (
      <div>
        <button>Click me</button>
        <p>Clicked X times</p>
      </div>
    );
  }
}

export default ClickCounter;
Enter fullscreen mode Exit fullscreen mode
  • Inside the same folder create another component named HoverCounter.js
import React from "react";

class HoverCounter extends React.Component {

  render() {

    return (
      <div>
        <h1>Hovered X times</h1>
      </div>
    );
  }
}

export default HoverCounter;
Enter fullscreen mode Exit fullscreen mode

As you can see in both the ClickCounter and HoverCounter components we have to create a state which will be increased by one each time we click the button or hover over a text. So let's write the logic to implement this functionality.

 constructor(props) {
            super(props)
            this.state = {
                count:0
            }
        }

        incrementCount = () => {
            this.setState(prevState => {
                return {count: prevState.count + 1}
            })
        }
Enter fullscreen mode Exit fullscreen mode

Here, the initial state of count is set to zero and incrementCount will increment the value of count by 1.
Now, one way to make the components work is by adding the above piece of code in both the components and trigger incrementCount on button click in ClickCounter and on mouse hover on HoverCounter.
Another way is by using a Higher Order Component where we can put the count and incrementCount and then pass them down as props to ClickCounter and HoverCounter.
To do that let's open our withCounter.js file and write some code.

import React from 'react'

const UpdatedComponent = (OriginalComponent) => {
    class NewComponent extends React.Component{
        constructor(props) {
            super(props)
            this.state = {
                count:0
            }
        }

        incrementCount = () => {
            this.setState(prevState => {
                return {count: prevState.count + 1}
            })
        }
        render(){
            return <OriginalComponent count={this.state.count} incrementCount={this.incrementCount } />
        }
    }
    return NewComponent
}

export default UpdatedComponent
Enter fullscreen mode Exit fullscreen mode

In this HOC, UpdatedComponent is an arrow function that takes OriginalComponent as a parameter. In our case, we will send ClickCounter and HoverCounter as the OriginalComponent parameter.
In this HOC, we are passing down count and incrementCount down as props in the OriginalComponent. Finally, we return NewComponent which, we can call an enhanced version of the OriginalComponent.

  • Now we will send ClickCounter and HoverCounter as parameters to the HOC withCounter.js. So, ClickCounter.js will be -
import React from "react";

import UpdatedComponent from "../HOC/withCounter";

class ClickCounter extends React.Component {
  render() {
    const { count, incrementCount } = this.props;
    return (
      <div>
        <button onClick={incrementCount}>Click me</button>
        <p>Hovered {count} times</p>
      </div>
    );
  }
}

export default UpdatedComponent(ClickCounter);

Enter fullscreen mode Exit fullscreen mode
  • And, HoverCounter.js will be

import React from 'react'
import UpdatedComponent from "../HOC/withCounter";

class HoverCounter extends React.Component  {
  render() {
    const { count, incrementCount } = this.props;
    return (
      <div>
        <h1 onMouseOver={incrementCount}>Hovered {count} times</h1>
      </div>
    );
  }

};

export default UpdatedComponent(HoverCounter);

Enter fullscreen mode Exit fullscreen mode

And, the final output is,

HOC
Now, in this example, we can also solve the problem by lifting the state up to a common parent component. But in a larger application, if the counter components ClickCounter.js and HoverCounter.js are scattered, lifting state would not be the correct solution. In cases like this, we can use a Higher Order Component.
So, this is how a Higher Order Component works.
Thank You!!

Top comments (0)

🌚 Browsing with dark mode makes you a better developer by a factor of exactly 40.

It's a scientific fact.