Why you should be hooked on React Hooks!
There hasn’t been a new feature since I started using React that had me stoked as much as React Hooks has. React Hooks is a feature introduced in React 16.8. It allows you to use state and lifecycle methods inside a functional component.
In this blogpost, I’m not going to explain every single hook there is, but I’m going to explain the most common ones and show you why I’m hooked on them.
Functional components
By using functional components, you write code that is easier to read, test and you usually end up with less code than its Class counterpart. A downside of functional components was not having any lifecycle methods. Now you can use the useEffect hook to use lifecycle events even in functional components.
Let’s make one thing clear. Class components did not get removed with the launch of React 16.8. Functional components just got a boost.
Let’s write some code!
Let’s say I’ve got a simple album library application with an album overview page. Inside the Overview I want to do a fetch call to get the albums and show them to the user. With a Class component something like this would work:
I’m using a Class component because I want to keep the albums inside a state and use the lifecycle method componentDidMount as a trigger to fetch my data.
To rewrite it as a functional component I could do something like this:
This would mean that I would have to put the fetch logic somewhere up the ladder and pass the albums as a property.
Introducing hooks
useState & useEffect
Let’s have a look at how I can change my functional component example to have it match the Class component example.
As a starter I could use the useState hook to manage state properties inside the component.
I imported useState from “react”, removed the property which was passed from above and added the actual useState which has an empty array as default value.
At the moment the component does nothing other than displaying an empty list. What I want is to introduce the useEffect hook which is pretty much componentDidMount, componentDidUpdate, and componentWillUnmount put into one function (which is amazing).
I don’t want to get too deep into useEffect for now, but let’s see how I can use it in our example.
In this example useEffect only triggers once when the component gets rendered. You can see that because the second param that is passed to useEffect is an empty array. You can pass properties inside that array to trigger useEffect every time the property changes.
Let’s take this example refetching all albums every time an album is clicked (which is pretty useless, but I’m going somewhere with this).
On my Album component I’ve put an inline function. That means that every time the component renders, a new reference is being made, which can cause a lot of overhead. Again: this is something that can be fixed.
Memoizing
According to Wikipedia:
In computing, memoization or memoisation is an optimization technique used primarily to speed up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again.
useCallback & useMemo
React has two built-in hooks for memoizing: useMemo is used for expressive calculations, whilst useCallback is used for passing callbacks.
Just like useEffect, useCallback takes a function as its first prop and an array as its second with the same use.
By using useCallback, the reference is only going to update when an album is clicked. In this specific example it does not give much benefit to the case, but if in some cases a property changes or another rerender triggers it does. It’s good practice to avoid inline functions and in functional components useCallback is the way to do that.
Memo
Memo is also something added in React 16.8, but isn’t technically a hook. It’s a HOC. It basically memoizes your entire component. It does a shallow comparison of your passed properties and as long as they don’t change, it does not trigger a rerender.
It’s very simple to implement. You just wrap your component with memo and it’s done.
Hooks, hooks and more hooks
Next to the hooks I explained, there are many more. Here’s a list of all of them:
- useState
- useEffect
- useContext
- useReducer
- useCallback
- useMemo
- useRef
- useImperativeHandle
- useLayoutEffect
- useDebugValue
Custom hooks
Next to all those fancy hooks, you can actually make your own. Building your own Hooks lets you extract component logic into reusable functions. It’s a great way to reuse functionality.
Conclusion
To conclude this blog post, I would definitely recommend hooks as a great alternative to the common design patterns. They are not only a great alternative, they also improve the readability of your code. Hooks do not entirely replace Class components, but in most cases they do. In addition, they just make things cleaner. I could go on about Hooks, but I will keep that for later. Stay tuned for the next blog post!