How to migrate from Recompose to React Hooks

Terence Jeong
Station Five
Published in
10 min readJan 8, 2019

In late 2018, the React team recently released the RFC for the new fancy React Hooks API. This new API was met with excitement, eagerness and anticipation by the React Community and me. That being said, it was also met with some trepidation. Was this the end of the Higher Order Components(HOC) and Render Props era? Does this mean I have to re-architect my projects?

I personally believe in the functional programming paradigm and as a result I try to stay away from class components within my React projects. I find that class components have the following downsides.

  • Confusing (for both humans and computers, especially binding and ‘this’ keyword.)
  • Component is very rarely reusable.
  • Logic spread over lifecycle methods.
  • Hard to test compared to functional components.
  • Compiled code size and compile time.

Instead, I use the Higher Order Component Pattern with the Recompose library to build reusable component logic in a composable way. By using pure functions and functional programming concepts I ensure the following advantages.

  • The code is highly reusable.
  • Functions can be composed together.
  • The code is easily tested.
  • There aren’t any observable side effects.
  • The data is immutable.

However, Andrew ‘acdlite’ Clark, a core team member of the React team and author of the hugely popular Recompose library announced that

“Hooks solves all the problems I attempted to address with Recompose three years ago, and more on top of that. I will be discontinuing active maintenance of this package (excluding perhaps bug fixes or patches for compatibility with future React releases), and recommending that people use Hooks instead.”

Given this announcement, I thought it was important to look into using Hooks and how it is different to my current use of HOC’s with the recompose library.

The purpose of this article is to show you,

1. How I use recompose and the HOC pattern to compose functions to give functional components ‘state’.

2. How easy it is to move from recompose to the new React Hooks API and reduce the use of HOC or Render Props.

** Spoiler Alert **
It is very similar, and I am extremely excited to see how and which direction Hooks will go!

Class Components

Let’s take a look at the code below. It is a simple form that allows the user to submit their first name, last name and age.

This form is your standard class component and to me it has the following problems:

  1. Unable to reuse stateful logic between components
  2. Each input needs it’s own onChange handler and for a large form it could get quite tricky to organise these handlers.
  3. Remembering to bind this or when to use arrow functions gets confusing.
  4. The file does not allow separation of concerns. This class component is managing state, as well as rendering a view.

Higher Order Component Pattern

Let’s see how we can take a functional approach using the HOC pattern and recompose so we can:

  1. Allow the separation of concerns.
  2. Reuse stateful logic between components.

Firstly, if you are coding along assuming you have done create-react-app, please note that you will need to install the recompose library. This can be done by running yarn add recompose.

So our component is going to be a functional component that is only concerned with displaying the props that it is given. It has no idea about state or anything else.

Looking at the code below we can see that it is very similar to the form from the class component above. Except this time, it is just a function and unlike the class component, it doesn’t give a hoot about where the props are from, or even what they are. The sole job of this component is to render the props it has been given.

But how did it get the props? From the Higher Order Components of course!

Looking at the code below, we can really see the power of the recompose library. We have created a function that takes a Base Component, and ‘enriches’ it with props and returns a new component.

withState is a HOC that provides the following

  1. The first argument declares the state variable, in this case firstName, lastName, age
  2. The second argument is the function to update the state variable, in this case setFirstName, setLastName, setAge
  3. The third argument is the initial value for the state variable, in this case Jon, Travis, 22

If this is confusing, basically what this enhancer is doing is replicating the state object we have in our class component. These values are passed to the base component as props instead of state. We also do not need to bind any handlers since they are declared as the 2nd argument in the withState HOC.

State from the Class Component.
Props from the Functional Component.

withHandlers is a HOC that accepts a set of props and returns a function handler. This function handler is passed to the base component as props.

compose is a handy utility function from recompose that is used to compose multiple higher order components into a single, nested higher-order component. In this case, it allows use to compose our multiple withState and withHandlers together.

Putting it all together we can now use this functional component anywhere in our app.

So what are the advantages of this pattern?

  1. You can see that the code is a lot more organised. If I need to add or remove logic from the component, I can simply do so in the enhancer file.
  2. It is a lot more reusable. I can share the stateful logic between components via the enhancer.
  3. I can compose many HOC’s
  4. Easily testable, since it is just a pure function.

React Hooks

Ok so now are are the really good stuff, converting the form using the new React Hooks API.

Firstly, what are React Hooks? From the React Docs.

Hooks are functions that let you “hook into” React state and lifecycle features from function components.

In super simple terms, React Hooks allow our functional components to have local state and lifecycle features! WHAT?!

The whole point of me using the HOC pattern was to reuse stateful logic between components. But as you see this meant that I had to restructure my components and there is a bit of boilerplate. If you look at the image below you can see ‘wrapper hell’ and this is generally pretty common when using the HOC pattern.

Wrapper Hell

As you can see, it can get quite messy up in here.

Hooks will allow you to use stateful logic without changing the component hierarchy and clean up the mess we see before us.

useState Hook

To make it as simple as possible, let’s look at the useState hook.

If you look at the code above, there are some things that stand out. The useState hook is used to manage local state in function components. Much like recompose withState the useState hook gives the functional component local state.

  1. The first item in the array, is our state variable. In this case it is firstName, lastName and setAge
  2. The second item in the array, is what we use to update the state variable. In this case it is, setFirstName, setLastName, setAge
  3. The value in the useState function is the initial value to the state variable. In this case it is Jon, Travis 23

Does this look familiar? It should! It follows a very similar pattern to withState HOC from recompose. Pulling it all together, let’s see what the form looks like just using hooks.

Through the useState hook we were able to completely remove the need for HOC’s and if we have a look at our component tree.

What a clean component tree!

Isn’t that absolutely beautiful! It is so tidy and will grow into a beautiful easily trackable tree. Just to highlight the difference here are both of them together.

And if we compare what our form looked like as a Class component compared to the functional component powered by hooks have a look at the image below.

useEffect Hook

As mentioned before, hooks allow functional components the ability to manage state and lifecycle methods (aka side-effects). We saw how to manage state with the useState hook. The useEffect hook comes into play for life cycle methods / side-effects which are usually used for interactions with the Browser/DOM API.

Let’s take a look at the componentDidMount lifecycle. In your classic class component we have the following. We can see that when the component is mounted it will set the state of initial value to ‘Down with classes!’

Now how would we replicate this with the useEffect hook? Well firstly, let’s look at the useEffect hook in a bit more depth.

When you use the useEffect hook you are telling React that your component needs to do something after render. React will remember the function you passed and will call it after the DOM updates.

So in this case after the render, the useEffect hook will run and the initial value will be set using the setInitialValue function to ‘Functional Components FTW’.

So, 2 paragraphs ago I mentioned that the useEffect hook will run after the DOM updates. So doesn’t that mean in the code above we will be in an endless loop?

From the React Docs

If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run.

So as you can see we passed an empty array meaning that it will only run once.

So why do we have to place it inside the functional component?

By doing so, you can access the state variable right from the effect. How you ask? Well since we have the useEffect hook in the functional component, it is within the functional components scope.

That means through closure, we can access the state variable. There is no special API required, it is just using normal Javascript closures! If you want a good description of closures, please check out Kyle Simpson’s You Don’t Know JS.

A more detailed useEffect example

So the custom hook above is responsible for determining if the screen size is mobile or not. Let’s just look at the useEffect section of the code.

So the key things to look at here is that after the component renders it will run the effect which will add the event listener to get the width of the screen.

But why is it returning a function?

Well, for useEffect if your effect returns a function, React will run that function when it is time to clean up. So in this case, we are removing the event listener. Sound familiar? It is like your componentWillUnmount.

However, I think it is a bit cleaner as it keeps the logic for adding and removing subscriptions close to each other since they are part of the same effect.

But why is there a value in the array now?

That’s a really good question. You know how I’ve mentioned many times now that useEffect will run after the component renders and the DOM updates. Well, by adding the width value in the array, you can tell React to skip applying an effect if the value hasn’t changed between re-renders.

So if the component re-renders, React will compare the values of the previous render and the next render. If they are the same, React will skip the effect, if they are different React will run the effect. Sound familiar? It is like your componentDidUpdate.

Custom Hooks

So we now know about useState and useEffect! Now the last thing I want to mention is custom hooks. WHAT?

That’s right, since hooks are just Javascript functions, you can write your own hooks that can be reused in the application and other applications. That literally means you can reuse stateful logic between components without HOC’s or Render props.

The hook above useIsMobile is a custom hook that can be used in any part of the application!

This is the most exciting part about hooks, the reusability. There is so much potential to grow an ecosystem of hooks to use in all your applications.

Now, I want to stress that there are a whole bunch more of React Hooks such as useEffect, useContext, useCallback, useMemo, useRef and many more. You can read all about them here, and I may even write some more about them down the track.

Conclusion

I hope this article has helped you understand how seamless it is to go from using the recompose library to hooks. The HOC’s approach is a purely functional way of coding in React and with solid coding conventions it results in robust code. There is absolutely nothing wrong with using this pattern, I still enjoy it and feel it makes me a better developer.

However, the potential to grow your own library of hooks, the ease of reusing stateful logic between components has me thinking that this will be the norm for React moving forward. I am extremely excited in this development and can’t wait to see the way hooks evolves!

--

--