Higher-Order Components (HOCs) are a pattern in React that allows you to reuse component logic. They are not part of the React API, but a pattern that emerges from React's compositional nature.
A Higher-Order Component is a function that takes a component and returns a new component with additional props or functionality.
HOCs are used to abstract and share common logic across multiple components.
To create an HOC, define a function that takes a component as an argument and returns a new component.
import React from 'react';
const withLogger = (WrappedComponent) => {
return (props) => {
console.log('Props:', props);
return <WrappedComponent {...props} />;
};
};
Use the HOC to enhance a component by passing the original component to the HOC function.
const MyComponent = (props) => {
return <div>{props.message}</div>;
};
const EnhancedComponent = withLogger(MyComponent);
// Usage
<EnhancedComponent message="Hello, World!" />;
The withLogger
HOC logs the props of the wrapped component to the console each time it renders.
Here is an example of an HOC that adds authentication logic to a component.
const withAuth = (WrappedComponent) => {
return (props) => {
const isAuthenticated = /* your authentication logic here */;
if (!isAuthenticated) {
return <div>Please log in to view this page.</div>;
}
return <WrappedComponent {...props} />;
};
};
const Dashboard = () => {
return <div>Welcome to your dashboard!</div>;
};
const ProtectedDashboard = withAuth(Dashboard);
// Usage
<ProtectedDashboard />;
Ensure your authentication logic is secure and reliable to protect sensitive information.
While HOCs provide great benefits, they can also add complexity to your component tree. Use them judiciously and consider other patterns like render props or hooks for certain use cases.
import React, { useState, useEffect } from 'react';
const withDataFetching = (WrappedComponent, url) => {
return (props) => {
const [data, setData] = useState(null);
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]);
return (
<WrappedComponent
data={data}
loading={loading}
error={error}
{...props}
/>
);
};
};
export default withDataFetching;
const UserList = ({ data, loading, error }) => {
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{data.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
};
const UserListWithData = withDataFetching(UserList, 'https://jsonplaceholder.typicode.com/users');
// Usage
<UserListWithData />;
Be mindful of prop collisions when using HOCs. Ensure that props passed to the HOC do not overwrite props passed to the wrapped component.
Higher-Order Components are a powerful pattern for reusing component logic in React. They help you write cleaner, more maintainable code by abstracting common functionalities into reusable HOCs.
Objective: Create a Higher-Order Component to enhance a component with additional functionality.
Create a Logging HOC:
Create a new file withLogging.jsx
and define an HOC that logs each render.
const withLogging = (WrappedComponent) => {
return (props) => {
console.log('Rendering component with props:', props);
return <WrappedComponent {...props} />;
};
};
export default withLogging;
Apply the HOC:
Create a component and apply the withLogging
HOC to it.
import React from 'react';
import withLogging from './withLogging';
const SimpleComponent = ({ text }) => {
return <div>{text}</div>;
};
const EnhancedComponent = withLogging(SimpleComponent);
// Usage
<EnhancedComponent text="Hello, HOC!" />;
By completing this task, you'll gain practical experience in creating and using Higher-Order Components to enhance the functionality of your React components.