ReactJS - Higher order Components
ReactJS - Higher-Order Components (HOCs)
Section titled “ReactJS - Higher-Order Components (HOCs)”A Higher-Order Component (HOC) is an advanced technique in React for reusing component logic. HOCs are not part of the React API, per se. They are a pattern that emerges from React’s compositional nature.
Concretely, a higher-order component is a function that takes a component and returns a new component.
const EnhancedComponent = higherOrderComponent(WrappedComponent);Why Use HOCs?
Section titled “Why Use HOCs?”- Code Reusability: Share logic across multiple components without repeating code (e.g., subscription to a data source, logging, conditional rendering).
- Props Manipulation: Add or modify props passed to the wrapped component.
- Abstraction: Abstract away complex logic or boilerplate, making components simpler.
While Hooks (like useEffect, useContext, and custom Hooks) have become a more common and often simpler way to share stateful logic and side effects, HOCs are still a valuable pattern, especially for cross-cutting concerns that involve modifying the component’s rendering or props in a declarative way.
Creating a Simple HOC
Section titled “Creating a Simple HOC”Let’s create a simple HOC that adds an extra prop to the component it wraps.
withExtraInfo.js (HOC)
Section titled “withExtraInfo.js (HOC)”import React from 'react';
// This is the Higher-Order Componentconst withExtraInfo = (WrappedComponent) => { // It returns a new functional component const ComponentWithExtraInfo = (props) => { const extraInfo = "This info is from the HOC!";
// Pass existing props along with the new prop return <WrappedComponent {...props} extraInfo={extraInfo} />; };
// It's good practice to set a display name for debugging ComponentWithExtraInfo.displayName = `WithExtraInfo(${getDisplayName(WrappedComponent)})`;
return ComponentWithExtraInfo;};
// Helper function to get the display name of a componentfunction getDisplayName(WrappedComponent) { return WrappedComponent.displayName || WrappedComponent.name || 'Component';}
export default withExtraInfo;MyComponent.jsx (The component to be wrapped)
Section titled “MyComponent.jsx (The component to be wrapped)”import React from 'react';
function MyComponent(props) { return ( <div> <h1>Hello, {props.name}!</h1> <p>{props.extraInfo}</p> {/* This prop comes from the HOC */} </div> );}
export default MyComponent;App.js (Using the HOC)
Section titled “App.js (Using the HOC)”import React from 'react';import MyComponent from './MyComponent';import withExtraInfo from './withExtraInfo';
// Enhance MyComponent with the HOCconst MyComponentWithExtraInfo = withExtraInfo(MyComponent);
function App() { return ( <div> <MyComponentWithExtraInfo name="User" /> </div> );}
export default App;When this App component renders, MyComponentWithExtraInfo will be MyComponent but with an additional extraInfo prop injected by the withExtraInfo HOC. The output would show:
Hello, User!
This info is from the HOC!
Key Considerations for HOCs:
Section titled “Key Considerations for HOCs:”- Don’t Mutate the Original Component: The HOC should return a new component, not modify the input component.
- Pass Unrelated Props Through: HOCs should pass through all props that are not relevant to their specific concern using the spread operator (
{...props}). - Composition: HOCs can be composed together for more complex transformations.
- Convention: It’s a common convention to prefix HOCs with
with, likewithRouterorwithSubscription. - Refs are not passed through: If you need to access a ref on the wrapped component, you’ll need to use
React.forwardRef.
HOCs are a powerful pattern for creating reusable component logic. While custom Hooks often provide a more straightforward solution for sharing stateful logic, HOCs remain useful for tasks like modifying props, abstracting rendering logic, or integrating with third-party libraries that expect a component.
Further learning resources:
- React Documentation on HOCs: https://react.dev/learn/HOCs (Note: The new React docs prioritize Hooks, but the legacy docs have good HOC info.)
- Custom Hooks: https://react.dev/learn/reusing-logic-with-custom-hooks