React is popular for its component modular structure which we can reuse it throughout the application. So once for all, we do some coding stuff that is repeated in the various components. To overcome this replication of code React has provided one of the most useful techniques to use the component logic from one single component i.e Higher-Order Component.
What is a Higher Order Component?
A Higher-Order component is a function that takes a component and returns a new component. It is the technique in ReactJs for reusing the component logic in various component modules. As we know react component props changes into UI whereas in HOC changes a component into another component.
Also, it helps to add additional functionalities to your existing component. Hoc’s are pure functions which means whatever data they are receiving will results in value based on data. Like whenever we need to change the returning values we can simply change the data input we are providing to the function.
How we use it into another component?
We can simply wrap a normal component with HOC by providing data input that it needs.
For example, we are wrapping our App by Hoc we made: Hoc(App)
Let’s see the use of HOC:
Step 1: Create one React.js project.
npx create-react-app my-app
cd my-app
npm start
Step 2: Create one new file inside the src folder called HOC.js
import React, { Component } from 'react';
const Hoc = (HocComponent, data) => class extends Component {
constructor(props) {
super(props);
this.state = {
data,
};
}
render() {
const { data } = this.state;
return <HocComponent data={data} {...this.props} />;
}
}
export default Hoc;
Now include this function into App.js:-
// App.js
import React, { Component } from 'react';
import Hoc from './HOC';
class App extends Component
{render() {
return <h1>Hoc Example</h1>;
}
}
export default Hoc(App);
So the above HOC picture will be clear when you look at the example listed below. You will have a clear picture of why HOC.
Let say we have two files with almost the same data and logic. File names as UserList.js and AdminList.js
AdminList.js
//AdminList.js
import React, { Component } from 'react';
import List from './List';
class AdminList extends Component {
constructor(props){
super(props);
this.state = { adminData : [{ firstname: 'Vaishali', lastname: 'Tyagi' }, { firstname: 'devendra', lastname: 'kumar', }, ] }}
listFunc = () => { const { adminData } = this.state;
return
adminData.map((item) => ( <List data={item} /> ))
}
render()
{ return (
<table>
<thead>
<tr>
<td>First Name</td>
<td>Last Name</td>
</tr>
</thead>
<tbody>
{this.listFunc()}
</tbody>
</table> );
}
}export default AdminList;
UserList.js-
//UserList.js
import React, { Component } from 'react';
import List from './List';
class UserList extends Component {
constructor(props){
super(props);
this.state = {
userData : [{ firstname: 'Kunal', lastname: 'Rai' }, { firstname: 'Vaibhav', lastname: 'soni', }, ] }
}
listFunc = () => {
const { userData } = this.state;
return userData.map((item) => {
return <List data={item} /> })
}
render()
{
return (
<table>
<thead>
<tr>
<td>First Name</td>
<td>Last Name</td>
</tr>
</thead>
<tbody>
{
this.listFunc()
}
</tbody></table>);
}
}
export default UserList;
Let us call UserList and AdminList in app.js. So the output is:
Okay from the above pictures we have seen both scenarios and both are somewhat similar. In both cases, we are doing the same thing. Just display the Admin and User list First Name and Last Name. So, here what we can do is make one Higher-Order Component and pass both the components as an argument when needed.
Let’s make Hoc.js inside the src directory.
// HOC.js
import React, { Component } from 'react';
const Hoc = (HocComponent, data) => class extends Component {
constructor(props) {
super(props);
this.state = {data: data,};
}
render()
{
const { data } = this.state;
return <HocComponent data={data} {...this.props} />;
}
}
export default Hoc;
The above file takes two arguments that are your component which has to be rendered and another with what data in the result. So it will return a new component with the modified data value.
Now we will refactor our repeated data and will pas the data through Hoc “data” argument.so our UserList.js and AdminList.js will look like below:
UserList.js
//UserList.js
import React, { Component } from 'react';
import List from './List';
class UserList extends Component {
listFunc = () => {
const { data } = this.props;
return data.map((item) => {
return <List data={item} />
}
) }
render()
{
return (
<table>
<thead>
<tr>
<td>First Name</td>
<td>Last Name</td>
</tr>
</thead>
<tbody>
{this.listFunc()
}
</tbody> </table>
);
}
}
export default UserList;
AdminList.js
//AdminList.js
import React, { Component } from 'react';
import List from './List';
class AdminList extends Component {
listFunc = () => {
const { data } = this.props;
return data.map((item) => (
<List data={item} />
))
}
render()
{
return (
<table>
<thead>
<tr> '
<td>First Name</td>
<td>Last Name</td>
</tr>
</thead>
<tbody>
{this.listFunc()}
</tbody>
</table>
);
}
}
export default AdminList;
App.js
import React from "react";
import Hoc from "./Hoc";
import UserList from "./components/UserList";
import AdminList from "./components/AdminList";
const App = () => {
const userData = [
{ firstname: "Kunal", lastname: "Rai", },
{ firstname: "Vaibhav", lastname: "soni", },
];
const adminData = [
{ firstname: "Vaishali", lastname: "Tyagi", },
{ firstname: "Devendra", lastname: "Kumar", },
];
const User = Hoc(UserList, userData);
const Admin = Hoc(AdminList, adminData);
return
( <> <User />
<br />
<Admin />
</> );
};
export default App;
So the output by using HOC :
Conclusion:
We add Hoc to our component so that we can take advantage of the reusability of code into somewhere modules. Most of the third-party libraries are using this feature to write another cool library. Former React versions provided mixins to handle reusability of code which has been deprecated so as to alternate solution we use HOC.
Thanks for scrolling this far. I hope you liked the article.
Reference: https://reactjs.org/