logo
Published on

High Order Component in ReactJs

Authors
  • avatar
    Name
    Ganesh Negi
    Twitter

Higher-Order Components (HOC) in React

A Higher-Order Component (HOC) is a design pattern in React that facilitates the reuse of logic across multiple components. Essentially, an HOC is a function that takes a component as input and returns an enhanced version with additional features, without modifying the original componentโ€™s structure or behavior.

Higher-Order Components (HOC) in React

Why Use Higher-Order Components?

๐Ÿ”น Enhances Component Functionality โ€“ HOCs add extra capabilities to components in a clean and modular way. ๐Ÿ”น Encourages Code Reusability โ€“ By defining logic in a single place, you can apply it across multiple components without code duplication. ๐Ÿ”น Maintains Component Purity โ€“ Instead of modifying a component directly, HOCs wrap them, preserving their original state and functionality.

Best Practices for Implementing HOCs

  1. Avoid Mutating the Original Component One common mistake when using HOCs is mutating the wrapped component instead of creating a new one. JavaScript allows direct modification of objects and functions, but React emphasizes immutability to ensure predictable behavior. Instead of altering the provided component, always return a new enhanced component.

โŒ Incorrect Approach:

const HOC = (WrappedComponent) => {
  WrappedComponent = () => {
    // Mutating the component - NOT recommended
  };
};

โœ… Correct Approach:

const HOC = (WrappedComponent) => (props) => {
  return <WrappedComponent {...props} />;
};

  1. Pass Unrelated Props to the Wrapped Component A well-structured HOC should not interfere with props that are unrelated to its core functionality. Instead, it should pass through all props to maintain component flexibility.

Example:

const withMousePosition = (WrappedComponent) => {
  const injectedProps = { mousePosition: { x: 10, y: 10 } };

  return (originalProps) => {
    return <WrappedComponent {...originalProps} injectedProps={injectedProps} />;
  };
};

This ensures that any original props passed to the component remain intact while still providing additional functionality.

  1. Maximize Composability with Currying HOCs can accept additional arguments to allow for more dynamic configuration. One of the most powerful ways to structure an HOC is by using currying, a technique widely adopted in libraries like Redux.

Instead of writing:

const EnhancedComponent = HOC(WrappedComponent, config);

We can structure it using currying for better composition:

const EnhancedComponent = connect(selector, actions)(WrappedComponent);

Breaking it down:

const HOC = connect(selector, actions);
const EnhancedComponent = HOC(WrappedComponent);

By composing multiple HOCs together, we create a pipeline of enhancements:

const enhance = compose(
  withMousePosition,
  withURLLocation,
  connect(selector)
);
const EnhancedComponent = enhance(WrappedComponent);

This approach makes it easier to apply multiple transformations in a clean, readable manner.

Important Considerations & Pitfalls

  1. Define HOCs Outside of Component Scope Creating HOCs inside a component function can lead to unnecessary re-renders and state loss because React treats them as different instances every time the component re-renders.

โŒ Incorrect Approach:

const Component = (props) => {
  const EnhancedComponent = HOC(WrappedComponent); // Wrong! Defined inside a function
  return <EnhancedComponent />;
};

โœ… Correct Approach:

const EnhancedComponent = HOC(WrappedComponent);

const Component = (props) => {
  return <EnhancedComponent />;
};

  1. Refs Do Not Automatically Pass Through HOCs React does not pass refs as props. If you add a ref to an HOC-wrapped component, it wonโ€™t refer to the original component but to the outermost HOC wrapper. To forward refs correctly, use React.forwardRef.

Final Thoughts

In this discussion, we explored Higher-Order Components (HOCs) in React and their role in enhancing component functionality without modifying the original component.

The key takeaways include: โœ”๏ธ Avoid mutating the original component โ€“ Always return a new enhanced component instead of modifying the input component directly. โœ”๏ธ Pass through unrelated props โ€“ Ensure that all props not directly related to the HOCโ€™s behavior are forwarded to maintain flexibility. โœ”๏ธ Leverage composability โ€“ Utilize the Component => Component pattern to maximize reusability and scalability. โœ”๏ธ Be mindful of caveats โ€“ Avoid defining HOCs inside components to prevent unnecessary re-renders and state loss, and use React.forwardRef to properly handle refs.

By following these best practices, HOCs can be a powerful tool for structuring reusable logic in React applications while maintaining clean, maintainable code.