Higher-Order Component (HOC)
A HOC is a function that takes a component and returns a new enhanced component. It is a pattern for reusing component logic.
ts
function withSomething(WrappedComponent) {
return function EnhancedComponent(props) {
// add logic, inject props
return <WrappedComponent {...props} extra="value" />;
};
}Real example - withAuth
tsx
function withAuth<T extends object>(WrappedComponent: React.ComponentType<T>) {
return function AuthGuard(props: T) {
const { user, isLoading } = useAuth();
if (isLoading) return <Spinner />;
if (!user) return <Navigate to="/login" />;
return <WrappedComponent {...props} />;
};
}
const ProtectedDashboard = withAuth(Dashboard);withLogger - debugging HOC
tsx
function withLogger<T extends object>(WrappedComponent: React.ComponentType<T>) {
return function LoggedComponent(props: T) {
useEffect(() => {
console.log(`${WrappedComponent.displayName} mounted`, props);
});
return <WrappedComponent {...props} />;
};
}Composing multiple HOCs
tsx
const EnhancedPage = withAuth(withLogger(withErrorBoundary(Page)));
// reads right to left - hard to follow
// compose utility helps
import { compose } from 'redux';
const EnhancedPage = compose(withAuth, withLogger, withErrorBoundary)(Page);HOC vs custom hooks
| HOC | Custom Hook | |
|---|---|---|
| Reuses | JSX + logic | Logic only |
| Adds to tree | Yes - wrapper node | No |
| Debugging | Wrapper hell | Clean |
| Modern usage | Rare | Preferred |
HOCs were the primary pattern before hooks. Today custom hooks replace most use cases. HOCs are still useful for wrapping third-party components or adding JSX-level behavior like error boundaries.
updated
did you know it?