What Is a Higher-Order Component In React?
A Higher-Order Components are advanced pattern in react. it is used for enhance and share functionality across multiple components.
A Higher-Order Component (HOC) is a function. first that takes a component as an argument and returns a new component with additional functionality.
HOCs are mainly useful for tasks like adding data-fetching, handle authentication or manage conditional rendering without rewriting code in every component.
This concept is similar to higher-order functions in JavaScript, which accept functions as arguments and return functions.
Higher-Order Components allow developers to reuse logic by wrapping components. and making them more flexible and efficient.
This is a syntax of a basic Higher-Order Component function:
const enhanceWithExtraInfo = (WrappedComponent) => {
return function EnhancedWrapper(newProps) {
return <WrappedComponent {...newProps} extraInfo="Additional Value" />;
};
};
In this syntax, enhanceWithExtraInfo is the Higher Order Component function and that is take the WrappedComponent as its parameter. it returns a new component is the EnhancedWrapper, that renders WrappedComponent with the original props and added extraInfo.
This method allow us to add new properties to the wrapped component without altering its original code.
Simple Example Of Higher Order Component
React HOCs are built using functional components or class components. the HOC modifies its functionality by injecting new props, managing state or adding lifecycle methods by wrapping the original component.
Basic example of how HOCs work:
import React from 'react';
// Basic Component
const WelcomeMessage = ({ user }) => <h2>Welcome, {user}!</h2>;
// Higher-Order Component for Styling
const applyHighlight = (ComponentToWrap) => {
return (incomingProps) => (
<div style={{ fontStyle: 'italic', color: '#2c3e50' }}>
<ComponentToWrap {...incomingProps} />
</div>
);
};
// Wrapped Component with Additional Style
const StyledWelcome = applyHighlight(WelcomeMessage);
export default StyledWelcome;
In this code:
- WelcomeMessage is a simple functional component that displays a greeting message.
- applyHighlight is the HOC that wraps WelcomeMessage and adding a bold style to its text.
- StyledWelcome is the enhanced version of WelcomeMessage with added styling.
We create a new component (StyledWelcome) without changing the original WelcomeMessage component by using the Higher Order Component.
Higher-Order Components Common Use Cases
- Access Control (Authorization): HOCs can restrict access to the components, based on user permissions or authentication status.
- Data Fetching: HOC can manage data fetching and pass the data to the wrapped component as props.
- Loading Spinners and Placeholders: HOCs can add a loading spinner until data are fully processed.
- Logging and Analytics: They can track and log user interactions with certain components for analytics purposes.
Example 1: Access Control Using Higher-Order Component
A common example of Higher-Order Component is implementing access control based on user authentication. Below, Created the HOC to showing protected component only to authenticated users:
import React from 'react';
// Higher-Order Component to handle access control
const withAccessControl = (ComponentToSecure) => {
return (incomingProps) => {
const userLoggedIn = incomingProps.userLoggedIn; // Authentication check
if (!userLoggedIn) {
return <h3>Please sign in to view this content.</h3>;
}
return <ComponentToSecure {...incomingProps} />;
};
};
// Component to be protected
const Dashboard = ({ username }) => <h1>Hello, {username}! Welcome back.</h1>;
// Secured version of the Dashboard
const SecuredDashboard = withAccessControl(Dashboard);
export default SecuredDashboard;
In this example, the withAccessControl function is a HOC, to check the user are authenticated or not. if the user is not authenticated so it will renders a message to asking them to log in, Otherwise it renders the ComponentToSecure function.
Based on the user’s authentication status we create a SecuredDashboard component that display different content by wrapping Profile with withAccessControl function
Example 2: Data Fetching with Higher-Order Components
Higher Order Components are used to fetch data and pass it as props to the wrapped component. Below the example provide to fetches data from API and provides it to the component:
import React, { useEffect, useState } from 'react';
// Custom HOC to fetch remote info
const withRemoteContent = (DisplayComponent, endpoint) => {
return (incomingProps) => {
const [content, setContent] = useState(null);
const [isBusy, setIsBusy] = useState(true);
useEffect(() => {
const retrieveData = async () => {
try {
const response = await fetch(endpoint);
const parsedData = await response.json();
setContent(parsedData);
} catch (fetchError) {
console.error("Failed to load data:", fetchError);
} finally {
setIsBusy(false);
}
};
retrieveData();
}, [endpoint]);
if (isBusy) return <p>Fetching content...</p>;
return <DisplayComponent data={content} {...incomingProps} />;
};
};
// Simple component to show list items
const ItemViewer = ({ data }) => (
<ul>
{data.map(entry => (
<li key={entry.id}>{entry.name}</li>
))}
</ul>
);
// Enhanced component with auto data fetching
const SmartItemList = withRemoteContent(ItemViewer, 'https://api.example.com/data');
export default SmartItemList;
In this example, withRemoteContent function is a HOC. that accepts a component (DisplayComponent) and a URL. the HOC fetchs data from the URL, handles loading and pass the fetched data to the DisplayComponent.
Separate the data-fetching logic from the ItemViewer component and making ItemViewer simpler and reusable by using withRemoteContent function.
Higher Order Component Considerations
🔹Prop Naming Conflicts : When a Higher Order Component adds a new props, like extraData and isAuthenticated, so It should not the same prop names in the wrapped component. Otherwise the HOC might be overwrite existing props and it causing bugs.
🔹Wrapper Hell : Don’t Use too many HOCs like layer after layer. it can make your components difficult to read, debug and mantain. this situation is called “Wrapper Hell.” instead of HOCs you can use React Hooks for many use-cases. Hooks are simpler and cleaner, specially for fetching data, using state or context access.