Using custom hooks to manage state
Tags: react, webdev, tutorial, javascript
Published: 2021-09-30 01:40:44

For a long time, Redux was the go-to choice for state management in React web applications. But, with the new addition of Hooks and stateful function components, we can achieve the same Redux results using these tools. Here I'm presenting you a way in which I use them to manage my state, especially when it becomes complex and abstraction is needed. 

To show this we're going to need an example to work on, and since I don't want to confuse you it'll be rather simple. But, make no mistake, this technique works at any level.

Imagine that we have an app that lets you save typefaces (which I'm calling fonts for simplicity) that you like on the server. Later, you'll want to retrieve a list of them. Also, you might want to delete or add fonts. Basically, we need the whole CRUD operations.

Let's start retrieving the list of fonts from the database. In this first version, I'm using a straight approach of putting all logic on the same component.

Here is how it works. First I've defined two state variables, _likedFontsList_ is intended to store a list of all the fonts retrieved from the server, and _isLoading_ is used to show a loading state while we're fetching the data.
Once the component is rendered, the useEffect hook is triggered and we fetch the data using Axios. If the request succeeds we change the loading state to false and store the response data (the liked fonts) on its corresponding variable (likedFontsList)

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aorqp85zlotfl515pwp4.png)

This is not a complex functionality but we already have kind of a mess here. As I stated previously, we're merging the logic for fetching the data and the logic for displaying it. Not good.
Let's fix it using a custom hook.

First, we create a hooks folder, and within it, we're going to create our useFonts hook. We're using this naming because it's React's recommended convention.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/155cam14w11e76anxxyn.png)

Now let's start coding its functionality.
First, we're going to move the state from the LikedFonts component to the useFonts hook.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ntn7d9jh97ofim5t0l26.png)


Now, let's move the useEffect so that we can fetch the data when the custom hook is called.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gvdnufx8g8jcp4vsgk60.png)


Finally, all we have to do is to return the information other components are going to need.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ultvp08zswylia5x6wwk.png)


Our custom hook is complete! Note how we've abstracted all the logic for fetching from the LikedFonts component. Now it looks more concise since we're dealing with only one thing here, fetching the fonts. This is great for many things including:

Reusability: Where or what is going to use this data? The hook doesn’t care! Just call it and there you have it! And from the other way, the caller doesn't care how the hook obtains that data.

We have a "contract": If we want to change something later, like the fetching method or even the schema of the data we receive, we can do it easily since we have it in only one place and more importantly, we have a "contract".  That is when we declared our return statement the first time we were agreeing to return an isLoading variable with a boolean value, and a likedFontsList variable with the liked fonts in a particular schema.
Later if we want to change the schema we can do it easily using a translating function from the new schema to the old one.

Enough talking! Let's implement our custom hook before it gets cold and losses its crunchiness.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r0xrwqpyl3wuofc586g3.png)

Look at that! We went from 24 lines of code to 12 a 50% less! Now you can see easily and understand what the LikedFonts component is doing, showing the liked fonts.

And there is even more to it. Remember that we needed all the CRUD operations? Well, we can implement all of them in the custom hook to make it even more powerful. Let's start adding a saveFont method to create a new record.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qto3xnx4aggwjk8l5k6l.png)
 
Also, we can handle the errors right here. 
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nyphglayc0hc46ntle75.png)
 
And just like that we can handle all the operations relate to the fonts in this hook. Furthermore, we can even use other custom hooks inside it (i.g. a useUser hook to send calls to the API only if the user is logged in)

That's all for the moment. If you found this helpful or interesting please like it or share it with your friends (I know you have). This is my first time sharing this content but I have far more things to tell you so stay tuned! I usually have other posts related to the same theme so that if you combine them you get even more benefits. So, if you want to unlock that power you can follow me. You don't have anything to lose, if you see something you don’t like just unfollow me.