In this article we will learn about custom hooks in React, their importance and how to create custom hooks.
What is custom hook?
We know that hooks like useState, useEffect are reusable components. Somtimes we make components that we have to reuse again and again in the application. In this case we can convert the component to hooks by extracting logic from it.
Need for Custom Hooks
The main reason for which you should be using Custom hooks is to maintain the concept of DRY(Don’t Repeat Yourself) in your React apps. For example, suppose you have some logic that makes use of some built-in hooks and you need to use the logic in multiple functional components. So, the easier way to do it is creating a separate function that wraps the logic inside it and then call it from those components.Here, the separate function you created is the custom hook.
Building a custom hook
Creating a custom hook is the same as creating a JavaScript function whose name starts with “use”. It can use other hooks inside it, return anything you want it to return, take anything as parameters.
Note: It is important to name your custom hooks starting with “use”, because without it React can’t realize that it is a custom hook and therefore can’t apply the rules of hooks to it. So, you should name it starting with “use”.
Let us first create a component where we are not creating custom hook
Javascript
import React , {useState ,useEffect} from "react" ; function FirstComponent(props){ const [counter , setCounter] = useState(initializer); // Increases the value of counter by 1 function resetCounter(){ setCounter(counter + 1): } useEffect(() => { // Some logic console.log(counter); } , [counter]); const clickedButton = resetCounter; return ( <div> <h1> This is the First Component</h1> <button onClick={clickedButton}> Click here! </button> </div> ); } export default FirstComponent; |
Suppose we have to use this counter in multiple components then we would require a custom hook that can perfrom the same function multiple times.
Creating a custom hook
Create the custom hook as shown in the example below
Filename- src/components/useCustomHook.js:
Javascript
import {useState , useEffect} from "react" ; // Remember to start the name of your custom hook with "use" function useCustomHook(initializer , componentName){ const [counter , setCounter] = useState(initializer); // Increases the value of counter by 1 function resetCounter(){ setCounter(counter + 1); } useEffect(() => { // Some logic that will be used in multiple components console.log( "The button of the " + componentName + " is clicked " + counter + " times." ); } , [counter , componentName]); // Calls the useEffect hook if the counter updates return resetCounter; } export default useCustomHook; |
Using the custom hook in components
To use the custom hook in your components just import the “useCustomHook” function from “useCustomHook.js” file in the “src” folder.
- src/components/FirstComponent.js: This component will import customHook
- src/components/SecondComponent.js: This component will also import customHook
- src/App.js: We will render the components in this file
Javascript
// First Component import React from "react" ; // importing the custom hook import useCustomHook from "./useCustomHook" ; function FirstComponent(props){ // ClickedButton = resetCounter; const clickedButton = useCustomHook(0 , "FirstComponent" ); return ( <div> <h1> This is the First Component</h1> <button onClick={clickedButton}> Click here! </button> </div> ); } export default FirstComponent; |
Javascript
// Second Component import React from "react" ; // Importing the custom hook import useCustomHook from "./useCustomHook" ; function SecondComponent(props){ // ClickedButton = resetCounter; const clickedButton = useCustomHook(0 , "SecondComponent" ); return ( <div> <h1> This is the Second Component</h1> <button onClick={clickedButton}> Click here! </button> </div> ); } export default SecondComponent; |
Javascript
// App.js import React from 'react' ; import './App.css' ; import FirstComponent from './components/FirstComponent' ; import SecondComponent from './components/SecondComponent' ; function App(){ return ( <div className= 'App' > <FirstComponent /> <SecondComponent /> </div> ); } export default App; |
Output:
Explanation:
Note that the useEfffect is called after the first render even though we declare the dependency array. That means the callback function passed to the useEffect hook is executed after the first render and when the variables in the dependency array get updated. There is no straight way to prevent this first execution.
Note that both the counters (defined in “usecustomHook”) of the two components are different. The two components use two different “counter” state variable(see “useCustomhook.js”), they don’t share the states. Therefore, in this React app, each component has its own “counter” state variable. Similarly, each component has its own useEffect and they are executed independently of each other. If the counter of the FirstComponent is updated, the useEffect of the FirstComponent is called, similarly if the counter of the SecondComponent is updated, the useEffect of the SecondComponent is called independently of the FirstComponent (See the above output).