React design patterns – Higher Order Components

What is a Higher Order Component (HOC)

  • HOCs are a React design pattern for sharing abstracted logic and behavior.
  • A HOC is a function that takes a component, wraps it with new functionality and returns the newly wrapped component.

Benefits

  • Code Reusability
    • Avoid duplication and keep your code DRY by abstracting common functionality into HOCs.
  • Composition
    • HOCs can be easily chained together to compose a component with multiple functionalities.
  • Conditional rendering
    • HOCs are great for conditional rendering. Rendering the supplied component under certain conditions e.g. if authenticated or admin.
  • Prop manipulation
    • A HOC can manipulate props before passing them to the wrapped component. Useful for adding additional props or updating existing ones.

Caveats

  • Wrapper hell
    • Excessive use of HOCs can lead to wrapper hell where a component is wrapped in multiple layers of HOCs. This can make the component harder to test and debug.
  • Prop collision
    • A HOC that injects props into the supplied component could unintentionally overwrite an existing prop.
  • Do you need a custom Hook instead?
    • Can your HOC functionality be expressed as a Hook?
    • Sharing functionality used within a component? create a custom Hook.
    • Sharing functionality used outside a component? create a HOC.

Anatomy of a HOC

  • A function that takes a component as an argument (can specify others too depending on HOC).
  • HOC naming generally starts with with. E.g. withStyles, withAuthentication, withLogging, withSomeFeature.
  • A new functional component is created and returned from the function along with the new behavior.
// Function name starts with with.
// Accepts a Component parameter.
const withSomeFeature = (Component) => {
  // Return new functional component. props
  // are intended for the wrapped component.
  return (props) => {
    const additionalProps = {
      propOne: true,
    };

    return <Component {...props} {...additionalProps} />;
  };
};

Using a HOC

// Component to adapt
import Textbox from "carbon-react/lib/components/textbox";

// withStyles HOC to apply styles to a supplied component
import withStyles from "./hocs/withStyles";

// Call withStyles with the component
// to adapt as an argument.
// The new wrapped component is returned.
// Give it a name and render as normal.
const StyledTextbox = withStyles(Textbox);

// Render instance of StyledTextbox
<StyledTextbox />;

If you need to use the newly wrapped component in multiple places export it from a shared location.

Examples

Live demo Prop manipulation examples Conditional rendering example

Leave a comment