ReactJS Hooks: I’ve been waiting for you

Paquitosoftware
4 min readNov 3, 2018

I have to admit that I was dissapointed when React team decided to ditch mixins from their API.
Yes, I understand the motivation and I also know it was for the better, but I didn’t like the alternatives: HOCs (at first) and render props components (later).

Both the alternatives were clever solutions to the share logic problem, but they were no elegant for me. Every time I used them I had that feeling of writing the best of the worst solutions but I didn’t could came up with a better one.

Now, with the new Hooks API proposal, I finally find the elegant solution I was eager to use.

IMPORTANT: Remember that this is an experimental feature yet. It’s NOT current part of the official API and we have to wait before using it in real projects.

Hooks are coming…

So, I’m really excited about this new API and the more I read about it and the more I experiment with it, the more I love it.

I want to show here some examples about how to use it and how them compare to the other traditional ways of sharing logic between components.

We have this simple APP to browse some podcasts that I call Podcaster.

You can find all the code for the application in this GitHub repository.

We have three pages in this application: home, podcast detail and episode detail.
Each one must load some external data to can be shown so I wanted to extract that behavior logic to a shared place.

Moreover, the home page has a simple filtering input element so the users can narrow down the list shown.

Let’s fitst implement this with a High Order Component:

And this is how we use that HOC from the home page view:

So, in our page component we rely on some new props (isLoading and externalData) that the HOC provides.

From the point of view of this page component I guess it’s easy to reason about it as we wrap it with another one and kind of earcn its behavior (it’s composition not inheritance).

My problem here is that the HOC doesn’t feel natural. We’re writing an (visual) component that only holds behavior and we have to subscribe to different lifecycle callbacks in the context of the wrapped component.

In terms on LOC, we have 51 (HOC) + 56 (page component) = 107.

Let’s move on and try the render prop component:

And this is how we use that component from the home page view:

Render prop components were the next step in the sharing logic evolution after the HOC but, as you can see, from the point of view of its implementation, they are almost identical.

I guess this is a more compositional way but I always found it ugly. I don’t like the code I have to write into my render components: there is more indentation and it’s slightly more complicated to understand.

In terms on LOC, we have 53 (render prop component) + 60 (page component) = 113.

Finally, let’s see how we implement this with the new Hooks API.
First, this is the custom hook:

And this is how we use that custom hook in the home page view:

Our custom hook is using several of the built-in hooks published in the new React API.

The page component is quite different because, as we are also using hooks in it to manage state, we don’t need it to be a class anymore (Hooks can’t be used in class components).

For me, this is a more natural approach.
We have a render method and we can import behaviour in it which is very easy to understand.

Maybe some will find this too imperative, but I feel like it’s super clear what the render method uses.

In terms on LOC, we have 36 (custom hook) + 38 (page component) = 74.

Ok, thanks for getting this far :)

As I said in the beginning, I’m very excited with the new Hooks API because it allows me to write so much cleaner code that is easier to understand and, thus, easier to mantain.

This is not the silver bullet that will solve all your problems when developing new solutions with ReactJS, but I feel it will help a lot.

There are some questions remainig about how they will evolve into the final release but I hope it doesn’t take too long.

Thank you very much for reading this.

--

--