freeCodeCamp/guide/english/react/higher-order-components/index.md

2.3 KiB
Raw Blame History

title
Higher-Order Components

Higher-Order Components

In React, a Higher-Order Component (HOC) is a function that takes a component and returns a new component. Programmers use HOCs to achieve component logic reuse.

If you've used Redux's connect, you've already worked with Higher-Order Components.

The core idea is:

const EnhancedComponent = enhance(WrappedComponent);

Where:

  • enhance is the Higher-Order Component;
  • WrappedComponent is the component you want to enhance; and
  • EnhancedComponent is the new component created.

This could be the body of the enhance HOC:

function enhance(WrappedComponent) {
  return class extends React.Component {
    render() {
      const extraProp = 'This is an injected prop!';
      return (
        <div className="Wrapper">
          <WrappedComponent
            {...this.props}
            extraProp={extraProp}
          />
        </div>
      );
    }
  }
} 

In this case, enhance returns an anonymous class that extends React.Component. This new component is doing three simple things:

  • Rendering the WrappedComponent within a div element
  • Passing its own props to the WrappedComponent
  • Injecting an extra prop to the WrappedComponent

Caveats

Higher-order components come with a few caveats that arent immediately obvious if youre new to React.

Refs Aren't Passed Through

While the convention for higher-order components is to pass through all props to the wrapped component, this does not work for refs. Thats because ref is not really a prop — like key, its handled specially by React. If you add a ref to an element whose component is the result of a HOC, the ref refers to an instance of the outermost container component, not the wrapped component.

The solution for this problem is to use the React.forwardRef API (introduced with React 16.3)

function enhance(WrappedComponent) {
  const wrapper = React.createRef((props,ref) => {
   return(
     <div className="Wrapper">
        <WrappedComponent
          {...props}
          ref={ref}
         />
      </div>
   )
  })
} 

Other Resources