Higher-order Components
Higher-order Components
A higher-order function is a function that takes one or multiple functions as its arguments and returns a new function.
In React, higher-order functions are used for reusing component logic. This pattern is commonly referred to as Higher-order Components (HOC).
HOCs are common in third-party React libraries, such as Redux’s connect and Relay’s createContainer.
Resources
Official Documentation https://reactjs.org/docs/higher-order-components.html
Video Lecture https://courses.reacttraining.com/courses/advanced-react/lectures/3065962
How it works
Concretely, a higher-order component is a function that takes a component as its argument and returns a new, enhanced component.
To help you wrap your head around the basic structure of a HOC, let’s look at a barebones implementation of a Higher-order Component:
Note that a HOC doesn’t modify the input component, nor does it use inheritance to copy its behaviour. Rather, a HOC composes the original component by wrapping it in a container component. A HOC is a pure function with zero side-effects.
Now that you’ve had a chance to get accustomed with the basic syntax for writing a HOC, let’s take a look at a real-world example:
And that’s it! The wrapped component receives all the props of the container, along with a new prop, data
, which it uses to render its output. The HOC isn’t concerned with how or why the data is used, and the wrapped component isn’t concerned with where the data came from.
Because withSubscription
is a normal function, you can add as many or as few arguments as you like. In this case, we decided to pass the data source as an argument to make our HOC even more re-usable.
When to use this pattern
As a rule of thumb, Higher-order Components should be used sparingly.
We want the bulk of our components to be stateless and solely focused on presentational concerns. For cross-cutting concerns, for example, when you need to provide state or functionality related to the top level application, consider pulling these out into a higher order component (HOC).
For a real-world example of how Higher-order Components are used in Shopify, take a look at the [withForm](https://github.com/Shopify/web/blob/master/app/utilities/form/with-form.tsx)
HOC.
When not to use this pattern
In most situations, you probably don’t need a Higher-order Component. Writing HOCs can be quite verbose and involves a lot of conventions and ceremony surrounding passing props vs consuming HOC props and hoisting statics.
They create indirection and are typically harder to reason about then the Children as function pattern, which we’ll look at in the next chapter.
For further reading on why HOCs might not be necessary for your use-case:
https://medium.com/tandemly/im-breaking-up-with-higher-order-components-44b0df2db052 https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce https://youtu.be/BcVAq3YFiuc
Common mistakes
Don’t Use HOCs Inside the render Method React’s diffing algorithm (called reconciliation) uses component identity to determine whether it should update the existing subtree or throw it away and mount a new one. If the component returned from render
is identical (===
) to the component from the previous render, React recursively updates the subtree by diffing it with the new one. If they’re not equal, the previous subtree is unmounted completely.
Normally, you shouldn’t need to think about this. But it matters for HOCs because it means you can’t apply a HOC to a component within the render method of a component:
The problem here isn’t just about performance — remounting a component causes the state of that component and all of its children to be lost.
Instead, apply HOCs outside the component definition so that the resulting component is created only once. Then, its identity will be consistent across renders. This is usually what you want, anyway.
In the rare cases where you need to apply a HOC dynamically, you can also do it inside a component’s lifecycle methods or its constructor.
Further reading
Last updated