Hello People! This is a short, composed and simply explained blog on a brief explanation of custom hooks, which is a topic for a beginner like me a bit intimidating. But no worries I will explain it to you right here.
Since you have clicked to read this blog that means you have a basic understanding of Hooks, particularly the useState()
hook.
Let us begin understanding through an example of a simple counter with only an increment button.
//App.js
import "./styles.css";
import { useState } from "react";
export default function App() {
const [value, setValue] = useState(0);
const incrementFunc = () => {
setValue((v) => v + 1);
};
return (
<div className="App">
<button onClick={incrementFunc}> + </button>
{value}
</div>
);
}
I hope you understand the basic useState() hook example of the counter above.
Here, we have called the useState()
hook once with initialized value 0
which provides a value
and a setter function setvalue
to change the value
. And in the UI
we have a button with a label +
and has an onClick function incrementFunc
and then we have a JSX {value}
to render the value produced by useState Hook. You can see the code running here https://codesandbox.io/s/usestate-example-b79djn
Now let's say we want to use two or more counters running in our App independently, So the simple way that our brain will answer might be this one -
//App.js
import "./styles.css";
import { useState } from "react";
export default function App() {
const [value1, setValue1] = useState(0);
const [value2, setValue2] = useState(0);
const incrementFunc1 = () => {
setValue1((v) => v + 1);
};
const incrementFunc2 = () => {
setValue2((v) => v + 1);
};
return (
<div className="App">
<button onClick={incrementFunc1}> + </button>
{value1}
<button onClick={incrementFunc2}> + </button>
{value2}
</div>
);
}
And it is perfectly fine. This works and solves our problem, you can check that out here :
https://codesandbox.io/s/usestate-example-2-szpb3h?file=/src/App.js:0-509
But here we have called the useState()
twice and what if we have to use it thrice or more than that, the code repetition increases which violates one of the basic principles DRY= Don't Repeat Yourself
of clean coding. So what is the solution in this case?
Here comes the concept of Custom Hooks.
Let me explain to you briefly that it is a JS function that we create ourselves when we want to share logic with other JS functions. It allows you to reuse some pieces of code in several parts of your App.
One of the rules of writing custom hooks is to start the hook name with keyword use.
In our case, we are using counter repeatedly so it makes sense to name our custom hook as useCounter.
So now this time we will call useState()
once directly and use it as many times as we wish, let me show you-
const useCounter = (input) => {
const [data, setData] = useState(input);
return [data, setData];
};
Here is our custom hook useCounter()
which calls useState()
and also return two values [data, setData].
so now we can reuse this hook in our code, Let me show you how to do it-
import { useState } from "react";
import "./styles.css";
const useCounter = (input) => {
const [data, setData] = useState(input);
return [data, setData];
};
export default function App() {
const [value1, setValue1] = useCounter(0);
const [value2, setValue2] = useCounter(10);
const incrementFunc1 = () => {
setValue1((v) => v + 1);
};
const incrementFunc2 = () => {
setValue2((v) => v + 1);
};
return (
<div className="App">
<h1>Learn Custom Hooks</h1>
<button onClick={incrementFunc1}> + </button> {value1}
<br />
<button onClick={incrementFunc2}> + </button> {value2}
</div>
);
}
Now it might have started to make sense like lego pieces and how to make custom hooks of our own. Here is just one thing that I should say the calling of useCounter()
twice here makes two completely different states having different values and different setter functions. You can view the live code for this example here- https://codesandbox.io/s/custom-hooks-explained-sbwjnl?file=/src/App.js
I hope you have found this blog easy to grasp as it was completely beginner friendly.
And If you have found this helpful do share your comments/ reviews.
Till then, Bye!