Skip to content

Higher-Order Components

A Higher-Order Component (HOC) is a function that takes a component and returns a new component with additional props or behavior. Common in pre-hooks React; largely replaced by custom hooks today.

HOC Pattern

const Enhanced = withAuth(MyComponent) wraps MyComponent to inject user props or redirect unauthenticated users. HOCs are composition at the component level.

Custom hooks extract the same logic with less nesting and better DevTools names. Read HOCs in legacy code; prefer hooks for new code.

function withAuth(WrappedComponent) {
  return function Authenticated(props) {
    const { user, loading } = useAuth();
    if (loading) return <Spinner />;
    if (!user) return <Navigate to="/login" />;
    return <WrappedComponent {...props} user={user} />;
  };
}

const ProtectedDashboard = withAuth(Dashboard);

HOC returns a new component wrapping the original with added behavior.

HOC Conventions

function withX(Component) {
  function WithX(props) { ... }
  WithX.displayName = `withX(${Component.displayName || Component.name})`;
  return WithX;
}
  • Set displayName for clearer React DevTools output.
  • Pass through unrelated props with {...props}.
  • Do not mutate WrappedComponent — return new function.
  • Watch ref forwarding — may need forwardRef in HOC.

HOC vs Hooks

Modern alternatives to common HOCs.

HOC Pattern Hook Alternative
withAuth useAuth() in component
withRouter useNavigate, useParams
withTheme useTheme()
connect (Redux) useSelector, useDispatch
withLoading useQuery isLoading

HOC Pitfalls

Wrapper hell: deeply nested HOCs hurt readability. Name collision on injected props. Static hoisting issues with some utilities.

  • Multiple HOCs create deep component trees in DevTools.
  • Injected prop names can clash with parent props.
  • Prefer single custom hook combining logic.

When HOCs Still Appear

Redux connect, legacy libraries, and cross-cutting wrappers in maintained codebases. Understand the pattern to refactor toward hooks incrementally.

Common Mistakes

  • Adding new HOCs instead of custom hooks in greenfield code.
  • Forgetting displayName on HOC wrapper.
  • Not forwarding refs through HOC layers.
  • Applying same HOC multiple times incorrectly.

Key Takeaways

  • HOCs wrap components to inject props or behavior.
  • Custom hooks replace most HOC use cases today.
  • Understand HOCs for reading legacy React code.
  • Set displayName and forward refs when using HOCs.

Pro Tip

When refactoring HOCs, extract inner logic to a hook first, then call the hook directly in the component.