The React team made quite an announcement when they revealed hooks in React. Hooks allow functional component to have state, access to lifecycle (called effects), context, and other stuffs. The community seems to have mixed opinions and some concerns about what this means for React moving forward. I played around with hooks during the weekend, and these are some of the reasons why I think hooks are good idea.
No more wrapper hell
If you are working with React, the picture above is probably awfully familiar. Until now, the main way to inject reusable logic to our component is by wrapping it in another component, usually achieved by creating an HOC or utilising the render props pattern.
With hooks, we can inject a reusable logic into our component without having to create HOC or use the render props pattern to do it.
For example, let’s say we want to create a counter, with simple increment and decrement handler. Because this feature might be used in a lot of place, we want it to be easy to be used by other components. This is how the implementation might look like using HOC.
And… this is how it looks with hooks.
No classes, no wrappers. Component can simply use the hook that contains the logic that it needs. The hook can expose APIs needed by the Component.
Currently, when we want to do something after a render is done, we would need to put the logic inside
componentDidUpdate. But, because
componentDidUpdate doesn’t get called after the initial render, we would need to implement the same logic inside
componentDidMount as well.
Apparently, there is a hook for this, it is called
useEffect. Basically, effect is something that will be called after every render. The code above can be simplified like this.
You might be thinking that it might be costly to do effect after every render, and you are probably right. The React team has thought about this and provided us with a mean for optimisation. The
useEffect hook also accept an array as the second argument. It will only run the effect again if the values in the array are different compared to the previous effect call.
But, another thing that is great about effects is that they are deferred after the browser layout and paint process. This allows the UI to stay responsive. Consider this badly implemented hook for example:
Observant readers will notice that this will cause the Component to keep re-rendering because the state is being updated after every render. This is exactly what happens when you call
componentDidUpdate. But, since
useEffect is deferred, the app will still be responsive to user inputs, even if it keeps re-rendering!
If you need your
effect to not be deferred, there are alternatives such as
useMutationEffect. You can read more about them on React docs.
Allow your code to be minified better
This, in my opinion, is by far the biggest reason why we should embrace hooks in React.
At the first part of this writing, I provided 2 gists that implement
counter, one with HOC, and another one with Hook. Let’s see how the generated bundles compare. I have put 2 gist links that contains the generated bundle (using webpack) below, you can take a look at them.
Other than the file sizes and the number of lines of code, notice that we still have some variables named as
onDecrease, etc. on the
usingHook.bundle.js gist, you will not find any.
1 KiB difference between these examples is actually quite surprising. You can expect bigger differences if your React app is bigger in size.
Hooks are powerful and quite mind-shifting addition to React. It allows developers share logic without creating a wrapper for everything. It allows our generated bundle to be smaller as well, which means a lot for developers working on the frontend side of the web. Smaller bundles are always better.