Table of Contents
Hi there👋,
When it comes to advanced topics in React, you must have heard about the HOC(Higher Order Component). Now this HOC is not that much complex to learn but avoid learning it directly by taking complex example. I’ll try to make it as simple as possible. If you prefer to watch video then click the link below.
What Kind of Problem HOC Solves?
Well, sometimes we have two different components which implements same logic. As you can see the following image,
Now for both of these components they have the same logic like counter. Let’s see the definition of HOC which mentioned in the reactjs.org.
What Is Higher Order Function (HOC)?
A higher-order component (HOC) is an advanced technique in React JS for reusing component logic. HOCs are not part of the React API, per se. They are a pattern that emerges from React’s compositional nature.
Now as mentioned above we can implement logic of component in single HOC and then we can use it in required components. Let’s see how this HOC is a pattern that emerges from React’s compositional nature and not a part of React API. It is an advanced technique. Checkout the following higher order functional component.
import React, { Component } from "react";
const HOC = (Component, data) => {
//You can do modification in data then pass it to the component
return class extends React.Component {
render() {
return <Component />;
}
};
};
export default HOC;
As you can see in the above function component, It is one of the pattern of HOC component where, it takes two arguments one is component
in which we want to add logic and second argument is data
. We can modify this data and then pass it to the component. Now this HOC will return a React component which returns more Enhanced component. Let’s try it in likes and comments component. Both of them are using the same logic as we use in the counter. Let’s create new file called Hoc.js
and write the following code.
1import React, { Component } from "react";
2
3const HOC = (Component, data) => {
4 //console.log("data", data);
5
6 return class extends React.Component {
7
8 constructor(props) {
9 super(props);
10
11 this.state = {
12 count: data,
13 };
14 }
15
16 handleClick = () => {
17 this.setState({
18 count: this.state.count + 1,
19 });
20 };
21
22 render() {
23 return (
24 <Component
25
26 CountNumber={this.state.count}
27 handleCLick={this.handleClick}
28 />
29 );
30 }
31
32 };
33};
34
35export default HOC;
36
37
Here we have implemented logic for counter.
-
Line no 3: Here, we can pass component and data.
-
Line no 6: In this line the higher order component(
HOC
) Returns a React component. -
Line no 7 to 19: This lines represents the same logic we use to implement counter.
-
Line no 25: Here we have passed state of the counter.
-
Line no 26: Here we have passed a function to increment counter state.
Now this higher order function pattern is not only for the class based component but we can also convert this into a functional React component. Let’s create a HOC which uses functional component,
import React, { useState } from "react";
const hoc = (WrappedComponent, data) => {
return function HOC(props) {
const [count, setCount] = useState(data);
const handleClick = () => {
setCount(count + 1);
};
return (
<WrappedComponent
countNumber={count}
handleClick={handleClick}
{...props}
/>
);
};
};
export default hoc;
As you can see in the above, HOC can be implemented using React functional component as well. Same as we did for the class component we are directly creating a state using useState
and initializing it with the data
props. You can use either class based HOC or functional HOC. Now let’s see how we can use this HOC. Create one file called LikesComponent.js
and add the following code.
1import HOC from "./HOC";
2
3class LikesCount extends Component {
4 render() {
5 return (
6 <div>
7 {this.props.CountNumber} <br />
8 <button onClick={this.props.handleCLick}>Like👍🏻</button>
9 </div>
10 );
11 }
12}
13
14const EnhancedLikes = HOC(LikesCount, 5);
15
16export default EnhancedLikes;
17
-
Line no 8: Here we have displayed no of likes.
-
Line no 9: This button is to increment likes.
-
Line no 15: Here we have used the HOC component. We have passed our original component
LikesCount
and no 5. Why 5? because let’s assume that there are already 5 likes then we can implement counter logic from no 5. This HOC component will return the enhanced component which we will store atEnhancedLikes
variable.
Line no 17: We have exported the new EnhancedLikes
component returned by HOC.
Now in simple terms, HOC took
LikesComopnent
anddata
then returned anEnhancedLikes
component by implementing Counter logic in it.
We can do the same for CommentComponent,
1import React, { Component } from "react";
2import HOC from "./HOC";
3
4class CommentsCount extends Component {
5 render() {
6
7 return (
8 <div>
9 Total Comments : {this.props.CountNumber} <br />
10 <button onClick={this.props.handleCLick}>Add Comment!</button>
11 </div>
12 );
13
14 }
15}
16
17const EnhancedComments = HOC(CommentsCount, 10);
18
19export default EnhancedComments;
20
21
Line 15: Here we are sending different data. (10 instead of 5)
Don’t forget to call enhanced Version of component that you have exported in your component file. Just like the following code,
import React from "react";
import "./App.css";
import EnhancedLikes from "./components/HOC/LikesCount";
import EnhancedComments from "./components/HOC/CommentsCount";
function App() {
return (
<div className="App">
<EnhancedLikes />
<EnhancedComments />
</div>
);
}
export default App;
After implementing this you will understand that we don’t have to write same logic for more components.
There are many uses of HOC such as, if user has already logged in and you want to check user’s login status in more then one component or pass user’s data then you can pass it to HOC then wrap HOC component around those components.
You can find Full-Code repository from here: HOC in React.