Hello π, Hope you're doing well.
Before diving into the custom hook, let's revise some points about Hooks in React.
Hooks
- useState
- useEffect
- useContext
- useRef
- useMemo
and many more...
All of the above mentioned are in-built hooks in React. Most of us have used these hooks many times while working with functional components.
What are Hooks?
Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class.
In simple words, Hooks are in-built functions which help React developers in managing state & lifecycle methods in a more clean & efficient way.
Rules of Hooks
- Donβt call hooks inside loops, conditions, or nested functions.
- Only call hooks from React functions.
You can read more about hooks from official docs - Hooks
All these in-built hooks are cool but what about creating our own custom hooks,
Is it possible?π―
YES!π₯
Let's create our own custom hook.
And we'll take the help of our legendary example - Counter App.
- Create a
CounterOne.js
file & write logic for increment, decrement & reset using in-built hook - useState.
import React, {useState} from 'react'
const CounterOne = () => {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count => count + 1)
}
const decrement = () => {
setCount(count => count - 1)
}
const reset = () => {
setCount(0)
}
return(
<div>
<h1>Count: {count}</h1>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<button onClick={reset}>Reset</button>
</div>
)
}
export default CounterOne
- Import
CounterOne.js
inApp.js
import CounterOne from "./CounterOne";
import "./styles.css";
export default function App() {
return (
<div className="App">
<CounterOne />
</div>
);
}
Now we can increment, decrement & reset the counter.
What if we want one more counter - easy no?
We'll copy the code of CounterOne.js
in CounterTwo.js
& Import it in App.js
.
import React, {useState} from 'react'
const CounterTwo = () => {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count => count + 1)
}
const decrement = () => {
setCount(count => count - 1)
}
const reset = () => {
setCount(0)
}
return(
<div>
<h1>Count: {count}</h1>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<button onClick={reset}>Reset</button>
</div>
)
}
export default CounterTwo
Here we go. we have now two counters on the view.
But doing copy/paste of whole logic isn't a good practice. We should avoid repeating ourselves.
Now we'll take advantage of creating a custom hook & extract our logic in a separate file.
- Create a
useCounter.js
file.
we must prefix the custom hook's name with use.
- Now we'll extract the logic part with in-built hook - useState. and yes, we can use in-built hooks in our custom hook.
import { useState } from "react";
const useCounter = () => {
const [count, setCount] = useState(0);
const increment = () => {
setCount((count) => count + 1);
};
const decrement = () => {
setCount((count) => count - 1);
};
const reset = () => {
setCount(0);
};
return [count, increment, decrement, reset];
};
export default useCounter;
At last, we return all the necessary variables & functions - count
, increment
, decrement
, reset
in an array.
That's it, we just made our own custom hook. π
Now we can use useCounter
hook in our functional components.
We just need to import this hook & use it using array destructuring.
const [count, increment, decrement, reset] = useCounter();
CounterOne.js
import React from "react";
import useCounter from "./useCounter";
const CounterOne = () => {
const [count, increment, decrement, reset] = useCounter();
return (
<div>
<h1>Count: {count}</h1>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<button onClick={reset}>Reset</button>
</div>
);
};
export default CounterOne;
CounterTwo.js
import React from "react";
import useCounter from "./useCounter";
const CounterTwo = () => {
const [count, increment, decrement, reset] = useCounter();
return (
<div>
<h1>Count: {count}</h1>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<button onClick={reset}>Reset</button>
</div>
);
};
export default CounterTwo;
Here's the code sandbox link - useCounter
Conclusion
Hope after reading this blog, now you know -
- how to create a custom hook.
- how to use it in a functional component.
If you find this blog as helpful, don't forget to share it.
Top comments (0)