DEV Community

Sahil Thakur
Sahil Thakur

Posted on

Create custom hooks in React

This post is originally written here along with the code snippets ->

It would be an understatement to say that the introduction of hooks changed a lot when it comes to development with React. In built hooks like useState, useEffect, useReducer etc. just run amock and are used widely when it comes to day to day React code writing. But one thing that is equally powerful that we will explore in this article is to create your own custom hooks in React.

Writing and creating your own custom hooks is a very useful and powerful method to share functionality among various components and keeping your code cleaner and DRY.

In this article, we’ll take a look at what custom hooks are, how to write custom hooks with two examples and when you should ideally go about writing custom hooks.

What are custom hooks ?
Technically, custom hooks are nothing but javascript functions with the difference being they start with the word use for linting benefits. Other than that, I like to think of hooks as functions which have the ability to work with state related issues in the components.

Let me try to make it a little more clear. Imagine you have two components which share nearly the same type of state and state manipulation for a state property of theirs, what you could do is write the code for handling and working with that state property in both the components separately but clearly that would be going against the DRY principle .

That is where custom hooks come into play, you can share code that involves manipulating state and working with state and component lifecycle methods by putting the code in a custom hook and then using that custom hook in whatever components you like.

Take useState as an example – it is nothing but a hook. It is a hook that we use in different components to manage the state of those components, the same way we can create our own hooks and manipulate state and other data accordingly. One of the key points to note is that hooks can use other hooks inside them as you will see in our examples.

In fact, if you are not using other hooks inside your custom hook – what is it? It’s just a simple javascript function , why bother categorise it into hooks?

Advantages of custom hooks
Custom hooks have a lot advantages over simple javascript functions and also just in general like :-

Keep your code DRY and non repetitive.
Use state and lifecycle methods even while sharing code
Create hooks others can use
Yes, you can easily create custom hooks and contribute to the open-source. To check out a list of some awesome and useful hooks in the npm library you can check this article out ->

Create custom hook in React 1
The first custom hook that we will be creating in this article is called useInput and it’ll be a very simple custom hook that we will be able to use with out input form elements in order to bind data and functionality with the input form element and the state.

Let us first take a look at how we would write something like it normally. Assume we want to create a component with two input elements that just take in say a name and an age. What we would usually do would look somewhat along these lines :-

Sorry for the typo of the submit function but well, we don’t have anything to do with it actually. The main things to notice is how we have created two input elements and they are using exactly the same logic for their updation and value setting (controlled input elements). We see that the value as well as onChange are nearly the same for both of them, aren’t they ?

To tackle such a situation, what we can do is create a custom hook called useInput and use it anywhere we want to control an input field. Let’s see how :-

So, this is the custom hook we have created in a file called useInput.js . Now, as I mentioned earlier, the only way in which hooks differ from regular functions is in the fact that custom hooks use other hooks inside them. In our custom hook we are using the useState hook.

Let us see line by line what the rest of the code is doing here, the first line is pretty simple – we declare a piece of state and its setter function. Next, we create an object that has properties of value and onChange. If you remember, these are the properties that our controlled input elements need to function properly. So, it is pretty evident that we’ll be spreading this object over the controlled element.

The logic for value and onChange is exactly the same. Just as a bonus I’ve added another function called reset which does nothing but reset the value of the state variable to the initial value.

In the end we are just returning the three things. Let us see how we can use this custom hook in our component now :-

This is the usage of the useInput custom hook in our good old useForm component. I don’t think this is anything fancy, we are just spreading the object of inputOptions inside the controlled input elements as I told before and using the newly created reset function to be called after the submit process.

The thing that is there to notice is that even though in this case we have just reduced a couple of lines of code for a couple of input elements, the possibilities here are endless. We no longer have to write higher order components to share state like this and can instead use smaller, leaner hooks to take care of that for us.

Create custom hook in React 2
In the previous example we saw how we shared a piece of code using custom hooks to manage similar state for two elements. What is even better is that using hooks, you can manage two components and their lifecycle methods if they are similar. Let us see how we can do that in this example.

One of the most famous custom hooks example is one where we store values to localStorage and I really find it awesome as well so let us learn to do that, assume we have a counter component which just increases or decreases a state of count. We also want to get and set values to the localStorage every time the component mounts or the value of this state variable changes.

Now, even though here we’ll use the useLocalStorage we’ll create only in one component but you can clearly see us wanting to get and set values from localStorage any time in our application. So, let us see how to do this -> with and without a custom hook.

So, this is a pretty simple component that tries fetching a value from localStorage and setting it up as the default value for the count state variable (or sets 0 as the fallback). Then there is the useEffect that updates the localStorage everytime the count variable gets changed.

Now, let us try to extract this entire logic to our custom hook that we’ll call useLocalStorage. This should be done in case there is more than one component that needs to store and manipulate localStorage values the same way this one is doing.

We have just extracted all the local storage logic into this custom hook. Now, as I told you, whenever you use a custom hook in a component, you get complete access to the state as well as the component lifecycle methods being used in that custom hook. Therefore, this useEffect hook being used in this custom hook is as good as it being used inside the component where this custom hook will be integrated into.

Let us go ahead and do that now, integrate this custom hook into our Counter component.

Using the useLocalStorage hook is even simpler than it was creating it, we just use it the same way we did useState earlier but the difference being that the logic for useState is already inside this useLocalStorage hook, along with the additional ability of using the useEffect hook as well.

Final words on custom hooks..
I find custom hooks a very very strong concept and a much cleaner concept than that of HOCs that were used earlier and would definitely recommend you to create your own custom hooks whenever you think the same logic is being used to govern a piece of state.

Remember that they are just simple JS functions with just the ability to use other hooks inside them.

If you want to learn about two awesome hooks that can help you improve your React app’s performance take a look here ->

Top comments (0)