Flat Preloader Icon

Higher-Order Components (HOCs)

Higher-Order Components (HOCs) are an advanced technique in React for reusing component logic. They are not a part of the React API but a pattern that emerges from React’s compositional nature.

What is a Higher-Order Component?

A Higher-Order Component is a function that takes a component and returns a new component. HOCs are used to add additional functionality to existing components without modifying them directly. This pattern is similar to higher-order functions in JavaScript, which take functions as arguments and/or return functions.
				
					const EnhancedComponent = higherOrderComponent(WrappedComponent);

				
			

Purpose of Higher-Order Components

  • Code Reusability: Encapsulate common behaviors, side effects, or data-fetching logic.
  • Separation of Concerns: Separate the logic from the presentation layer.
  • Abstraction: Abstract complex functionalities into a more manageable and reusable form.

Example of a Higher-Order Component

Creating an HOC

Here’s an example of a simple HOC that provides window dimensions to a wrapped component.

				
					import React from 'react';

function withWindowDimensions(WrappedComponent) {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        width: window.innerWidth,
        height: window.innerHeight
      };
    }

    handleResize = () => {
      this.setState({
        width: window.innerWidth,
        height: window.innerHeight
      });
    };

    componentDidMount() {
      window.addEventListener('resize', this.handleResize);
    }

    componentWillUnmount() {
      window.removeEventListener('resize', this.handleResize);
    }

    render() {
      return <WrappedComponent {...this.props} windowDimensions={this.state} />;
    }
  };
}

				
			

Using the HOC:

Now, you can use the withWindowDimensions HOC to enhance any component.

				
					import React from 'react';
import withWindowDimensions from './withWindowDimensions';

function DisplayDimensions(props) {
  const { width, height } = props.windowDimensions;
  return (
    <div>
      Window dimensions: {width} x {height}
    </div>
  );
}

export default withWindowDimensions(DisplayDimensions);

				
			

Best Practices with HOCs

  • Don’t Mutate the Original Component: Ensure that the HOC does not alter the original component but rather returns a new component.
  • Pass Through Props: Make sure the HOC passes all the props to the wrapped component.
  • Maximize Composability: Design HOCs to be composable, meaning you can use multiple HOCs together.
  • Static Methods: Copy over non-React static methods from the wrapped component to the HOC to preserve any static methods defined on the wrapped component.
  • Ref Forwarding: Use React.forwardRef to forward refs to the wrapped component if necessary

Common Use Cases for HOCs

  • Authentication: Wrapping components to ensure that only authenticated users can access them.
  • Data Fetching: Encapsulating data-fetching logic and providing the data as props to the wrapped component.
  • State Management: Managing state logic and providing state and state-modifying functions as props.
  • Performance Optimization: Adding performance enhancements like memoization or shouldComponentUpdate logic.

Example of Combining Multiple HOCs

You can compose multiple HOCs together to enhance a component with various functionalities.
				
					import withAuth from './withAuth';
import withWindowDimensions from './withWindowDimensions';

function UserProfile(props) {
  const { isAuthenticated } = props.auth;
  const { width, height } = props.windowDimensions;

  return (
    <div>
      {isAuthenticated ? <p>Authenticated</p> : <p>Not Authenticated</p>}
      <p>Window dimensions: {width} x {height}</p>
    </div>
  );
}

export default withAuth(withWindowDimensions(UserProfile));

				
			

Conclusion

Higher-Order Components (HOCs) are a powerful pattern for sharing and reusing logic across multiple components in React. By following best practices and understanding common use cases, you can effectively utilize HOCs to build cleaner, more maintainable, and more modular React applications.