5 min read
0%

Higher-Order Components (HOC)

Back to Blog
Higher-Order Components (HOC)

Higher-Order Components (HOC)

A higher-order component is a function that takes a component and returns a new component with added behavior. It’s a composition pattern that predates hooks.

Basic Pattern

function withLogging(WrappedComponent) {
  function WithLogging(props) {
    useEffect(() => {
      console.log(`${WrappedComponent.displayName} mounted`);
      return () => console.log(`${WrappedComponent.displayName} unmounted`);
    }, []);

    return <WrappedComponent {...props} />;
  }

  WithLogging.displayName = `WithLogging(${WrappedComponent.displayName ?? WrappedComponent.name})`;
  return WithLogging;
}

const LoggedUserCard = withLogging(UserCard);

Injecting Props

HOCs commonly inject props into the wrapped component:

function withCurrentUser(WrappedComponent) {
  return function WithCurrentUser(props) {
    const user = useCurrentUser();
    return <WrappedComponent currentUser={user} {...props} />;
  };
}

const ProfilePage = withCurrentUser(function({ currentUser }) {
  return <div>Hello, {currentUser.name}</div>;
});

HOC Problems

Prop collision: injected props overwrite consumer props with the same name.

Wrapper hell: stacking HOCs creates deeply nested DevTools output:

withRouter(connect(mapState)(withStyles(styles)(withLogging(MyComponent))))

Static method loss: HOCs don’t forward static methods automatically. Use hoist-non-react-statics.

Ref forwarding: refs don’t pass through HOCs by default — wrap with forwardRef.

HOC to Hook Migration

Most HOC patterns translate directly to hooks:

// HOC
const Connected = withCurrentUser(MyComponent);

// Hook equivalent
function MyComponent() {
  const user = useCurrentUser();
  // ...
}

Hooks are simpler, have no nesting overhead, and compose cleanly. For new code, prefer hooks.

When HOCs Still Make Sense

  • Libraries that must support class components
  • Wrapping third-party components you don’t control
  • Codebases with established HOC conventions you’re extending

Canvas is not supported in your browser