Understanding High Order Components with Examples
Higher-Order Components (HOCs) are a pattern in React for reusing component logic. An HOC is a function that takes a component and returns a new component with additional props or functionality.
Key Points about HOCs:
HOCs are Pure Functions: They do not modify the original component, but rather create a new one with enhanced capabilities.
Composition: HOCs help in composing components by adding behavior or props to them.
Reusability: They enable reusing component logic in different parts of an application without duplicating code.
Example:
Let's say we have a component that displays a list of users. We want to add the ability to fetch data from an API and handle loading and error states. We can create an HOC to handle the data fetching logic.
Step 1: Create a Basic Component
First, we create a simple UserList
component that displays a list of users.
// UserList.js
import React from 'react';
const UserList = ({ data }) => {
return (
<ul>
{data.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
};
export default UserList;
Step 2: Create the HOC
Next, we create an HOC called withDataFetching
that fetches data from an API and handles loading and error states.
// withDataFetching.js
import React, { useEffect, useState } from 'react';
const withDataFetching = (url) => (WrappedComponent) => {
return (props) => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(url);
const result = await response.json();
setData(result);
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
};
fetchData();
}, [url]);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <WrappedComponent data={data} {...props} />;
};
};
export default withDataFetching;
Step 3: Wrap the Component with the HOC
Finally, we use the withDataFetching
HOC to enhance the UserList
component with data fetching logic.
// App.js
import React from 'react';
import UserList from './UserList';
import withDataFetching from './withDataFetching';
const UserListWithFetching = withDataFetching('https://jsonplaceholder.typicode.com/users')(UserList);
const App = () => {
return (
<div>
<h1>Users</h1>
<UserListWithFetching />
</div>
);
};
export default App;
In this example:
UserList
is the base component that displays a list of users.withDataFetching
is the HOC that adds data fetching logic to any component.UserListWithFetching
is the enhanced component that fetches user data from the given API and displays it usingUserList
.
Benefits of HOCs:
Separation of Concerns: Logic for fetching data, handling loading states, and displaying data is separated.
Reusability: The
withDataFetching
HOC can be used with any component that needs data fetching.
Here are a few more common use cases:
1. Authentication : Ensuring that only authenticated users can access certain parts of your application is a common requirement.
// withAuth.js
import React from 'react';
import { Redirect } from 'react-router-dom';
const withAuth = (WrappedComponent) => {
return (props) => {
const isAuthenticated = // logic to check if user is authenticated
if (!isAuthenticated) {
return <Redirect to="/login" />;
}
return <WrappedComponent {...props} />;
};
};
export default withAuth;
Usage:
// SomeProtectedComponent.js
import React from 'react';
import withAuth from './withAuth';
const Dashboard = () => {
return <div>Dashboard</div>;
};
export default withAuth(Dashboard);
2. Logging: You might want to log certain actions or component renders for analytics or debugging purposes.
// withLogging.js
import React, { useEffect } from 'react';
const withLogging = (WrappedComponent) => {
return (props) => {
useEffect(() => {
console.log(`Component ${WrappedComponent.name} mounted`);
return () => {
console.log(`Component ${WrappedComponent.name} unmounted`);
};
}, []);
return <WrappedComponent {...props} />;
};
};
export default withLogging;
Usage:
// SomeComponent.js
import React from 'react';
import withLogging from './withLogging';
const Profile = () => {
return <div>Profile</div>;
};
export default withLogging(Profile);
Subscribe to my newsletter
Read articles from Diksha directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by