Can React Hooks API replace Recompose?

gvidon
ottofeller
Published in
3 min readOct 31, 2018

React team has recently released RFC for the new React Hooks API. In the same time Recompose’s (HOCs tool belt for React) author declared the end of the development of this library. Apparently these two events are not a coincidence but the evidence of an end of the HOCs era in React. And now we as developers are suggested to use React Hooks instead of Recompose in our workflow. Let’s see how different they are on examples.

Hooks force to code in an imperative way

compose() is one of the most valuable HOCs of Recompose which allows one to build new more complex HOCs in the declarative way, has no analog in new React Hooks API. This is not a disadvantage, but by design. With this new Hooks API you don’t need composition of functions, you just call hooks one by one in the body of component’s function and their effects and values are accumulated and applied to the component. In order to separate complex logic into reusable units all hooks calls can be moved into new function, which just like other hooks must be called within targeted component function body. Even though Hooks API is declarative it forces developers to some imperative methods.

Some meaningless component with reusable logic applied to it.

There is no analog of branch() in Hooks API. Without Recompose you have to explicitly use if or other conditional operators.

Changing loading state with hooks
The same in perfectly declarative way. props.data.loading comes from apollo client.

Another thing you will be missing without Recompose is withPropsOnChange(). It can be replaced by combination of useEffect(fn, [changed, values]) and useState().

Track component properties and generate full name when first and last names change
Same in recompose

These are just couple of simple examples. There are much more situations where you will have to replace elegant declarative solutions with the new imperative API.

Hooks are not enough explicit

Ok, useState() and couple of others are explicit enough. But it took me a while to figure out that useEffect() replaces componentDidMount() if it is being called with [] in place of second param. Without this second param it’s callback is triggered on every change of any property. Why not to add hooks which are named in the same way as class methods which everyone is familiar with?

The main problem with HOCs is that with the growth of component HOCs composition the flow of props can easily become hardly predictable. In a code with no proper maintenance one can easily get lost while trying to reason about which prop came from which HOC.

Atomic units of Recompose doesn’t have such an issue, as every of its HOCs which adds new props requires to explicitly add names to these props. The problem arises in bigger custom HOCs which provide child with props with predefined names and values.

Hooks solve this problem by moving internal logic properties (in Recompose everything is stored in props) into local vars of a function. One can now easily distinguish “private” variables and methods from business logic props which came into component from its parent.

Conclusion

HOCs approach with all its disadvantages is purely functional way of coding React apps. With careful maintenance and with coding conventions it results in a robust declarative code. That’s why it is sad to see the community refusing of using HOCs and vendors stopping to evolve their libraries in this direction.

Even though I’m personally a big fan of Recompose I really hope that Hooks API will become a good and helpful replacement of Recompose. Looking forward to see how and which direction to will it evolve!

OttoFeller is the software development company specialising in front end of complex web applications and in promising cutting edge technologies.

--

--