Adopt React Hooks in Legacy Apps using HoCs and Render Props

David Barral
Trabe
Published in
3 min readNov 25, 2019
Photo by Matthew Henry on Unsplash

Hooks may be the future of React applications, but they may not be the present of many applications.

As with many other React features, the React team has made it possible to adopt Hooks incrementally. Once you start using Hooks you extract common functionality to custom Hooks and use them in your functional components. Let’s see an example:

What happens in a legacy app if we are dealing with class components? How can we use those Hooks? Seems that there’s only one answer to this question: wrapping the legacy components with a functional component and using props to pass the Hook return values:

It works. However, we do not want to create a specific wrapper for each component that needs to use the useCounter Hook.

Enter the HoC. Enter the render prop

There are two widely adopted patterns that allow us to build reusable wrappers in React: HoCs and render props.

a HoC (higher-order component) is a function that takes a component and returns a new component.

We can generalize the pattern I showed before by using a HoC that, given a component, returns a wrapper that calls our custom Hook and injects the data returned by the hook to the wrapped component via props:

A component with a render prop takes a function that returns a React element and calls it instead of implementing its own render logic.

We can also generalize the pattern using a component with a render prop. This component will call the custom Hook and inject the data returned by the hook to the render prop function:

HoCs have some caveats and are not as flexible as render props. So, if I have to choose, I go for the latter. You can read the story written by my teammate Asís García: Advanced composition in React: cloneElement, HOCs and renderProps, to fully understand this claim.

Generalize the pattern with factories

Whichever the technic you use, if you have many Hooks you’ll be writing a lot of boilerplate. You can remove some of it by using a factory function that given a Hook returns either the HoC or the component with the render prop.

Let’s see the HoC factory first:

And now, the render prop factory:

Notice that, in both cases, we added two configurable mappings that translate between initial props and the Hook initial value, and between the Hook return value and the injected props. In the example, only the props mapping is needed. If the Hook returns an object instead of an array, no mapping is needed.

Summing up

HoCs and render props are powerful technics that can help us solve many problems just by leveraging functions, props and composition. They allow us to build really flexible and reusable components, and, as we’ve seen in this story, Hooks can be used in legacy applications with class componentes thanks to these technics.

--

--

David Barral
Trabe
Editor for

Co-founder @Trabe. Developer drowning in a sea of pointless code.