Puja Kundu
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?ExampleLet’s make a simple React application that will count the number of times you click on a button and hover on a text.
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; import React from "react"; class HoverCounter extends React.Component { render() { return ( <div> <h1>Hovered X times</h1> </div> ); } } export default HoverCounter;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} }) }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 UpdatedComponentIn 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.
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); 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);And, the final output is,
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!!
Puja Kundu is an aspiring developer.