Custom Hook - ReactJS
Tags: react, tutorial, webdev
Published: 2022-05-13 15:03:50

Hello 👋, Hope you're doing well.
Before diving into the custom hook, let's revise some points about **Hooks** in React.

## Hooks
   
1. useState
2. useEffect
3. useContext
4. useRef
5. 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**
1. Don’t call hooks inside loops, conditions, or nested functions.
2. Only call hooks from React functions. 

You can read more about hooks from official docs - [Hooks](https://reactjs.org/docs/hooks-intro.html)

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**.

1. Create a `CounterOne.js` file & write logic for **increment**, **decrement** & **reset** using in-built hook - useState.

```javascript
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
```
2. Import `CounterOne.js` in `App.js`

```javascript
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.

![counter app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lhoqyf71hpaav8d7ry3k.png)

**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`. 

```javascript
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.

![Two counter app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d4v2sctq8wtkqogetcz0.png)

**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.

3. Create a `useCounter.js` file.

> we must prefix the custom hook's name with **use**.

4. Now we'll extract the logic part with in-built hook - useState. and yes, we can use in-built hooks in our custom hook.

```javascript
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.

```javascript
const [count, increment, decrement, reset] = useCounter();
```

**CounterOne.js** 

```javascript
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**

```javascript
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](https://codesandbox.io/s/usecounter-tqz8qn?file=/src/CounterTwo.js)

## Conclusion
Hope after reading this blog, now you know - 
1. how to create a custom hook.  
2. how to use it in a functional component.

If you find this blog as helpful, don't forget to share it.

Thank you 🙂
Connect with me on - [Twitter](https://twitter.com/helloAbhishekk)  [Instagram](https://instagram.com/abhishekgautam.ig)