Higher-Order Components
Learn how higher-order components work and how to make them.
We'll cover the following
Refactoring with higher-order components
The power of React is that it allows you to express web apps in individual units called components. But the rules for assigning different bits of functionality to different components aren’t always clear. In principle, any React app could be expressed as a single monolithic component. Or, at the opposite extreme, every DOM element in the page could be managed by its own micro-component.
A good rule of thumb is that components should be built so that each component has only one job. Components with multiple responsibilities are a good candidate for being split up. These distinctions are intuitive, not technical. No automated process is going to tell you whether a component has multiple responsibilities. Still, thinking in these terms will help you as you work to keep code manageable. The more complex an individual component is, the harder it’ll be to make changes to it.
This chapter is about splitting up complex components into simpler pieces using a pattern called higher-order components (HOCs). You’ll add new functionality to the carousel component from the previous chapter while actually simplifying the core component by extracting some of its logic to an HOC. And you’ll learn how to use the React Devtools to see how different components are interacting in your browser.
Making higher-order components
In the abstract, a higher-order component is defined as any function that takes a component and returns another component. Typically, the component returned by the HOC function is a wrapper around the original component that adds functionality. Here’s a simple example:
const BindProps = (Component, boundProps) => { // 1
const ComponentWithBoundProps = props => (
<Component {...props} {...boundProps} /> //2
);
ComponentWithBoundProps.displayName =
`BindProps(${Component.displayName || Component.name})`; // 3
return ComponentWithBoundProps;
};
const CarouselWithTestAttr = BindProps(Carousel, { // 4
'data-test-id': 'carousel',
});
- The
BindProps
HOC takes two arguments, a component and a props object, to “bind” to that component. - Since the
boundProps
passed to the HOC are spread into the component after theprops
is passed directly, theboundProps
takes precedence. displayName
is a special property that gives React components a name for debugging purposes. We haven’t had to deal with it so far because JavaScript functions and classes have aname
property that usually works as a fallback. But for a dynamically generated component like this one, you’ll need to set the name manually. Using a name with the form"HOC(Component)"
is a common convention.- Here,
BindProps
is used to generate a component that behaves exactly likeCarousel
, except that it will always receivedata-test-id="carousel"
.
Get hands-on with 1400+ tech skills courses.