React custom Hooks are easy than you think
Tags: react, webdev, api, beginners
Published: 2022-06-21 14:31:22

ReactJS provides a lot of built-in hooks that you can use, but along with that we can also create our own custom hooks depending on our requirement.

> When we have a component logic that needs to be used by multiple components, we can extract that logic to a custom Hook and use it on every component.

Custom hooks are nothing more than a normal javascript function whose name starts with "use". The main reason for creating custom hooks is to follow the "**DRY**" (Don't repeat yourself) principle. We can simply create a custom hook and reuse it.

Before moving any further, let's see some examples of custom hooks which will help you in getting an idea on when to use custom hooks.

♾️ **useInfiniteScroll** hook : 
Suppose you had a website, in which you need to render a huge amount of data on the screen. So, instead of fetching all the data at once and rendering it on the user's screen you can fetch a fraction of data, and render it. Now when the user scrolls to the bottom of the page we can simply fetch the next fraction, and render it again. 
This saves our server bandwidth, improves response time and user experience.

![useInfiniteScroll](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wai17nldm97d1hxclloc.gif)



📄 **useCopyToClipboard** hook : 
You might have seen a little "copy to clipboard" button on code snippets (shown below). To implement such a feature, we can simply create this custom hook, and  call it whenever and wherever we want.

![Copy to clipboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3drll3w96ivxlnn6mo5v.png)



⬇️ **useFetch** hook : 
It's job is to simply fetch data from an API and return it to the component. We will be implementing this hook in this tutorial. (this is how it will look)


![useFetch](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gf1kj675505wnmg7hhoc.png)


So, now I hope that you might have some understanding about what exactly are custom hooks and when to use them.
Let's start with the useFetchJoke hook.

For this tutorial, we will be creating a simple react app which will render a random dad joke using [icanhazdadjoke](icanhazdadjoke.com/) api, and when we click on the "**get new joke**" button, our custom hook will send us a new joke. PRETTY SIMPLE, RIGHT !!


Create a new react app
```
npx create-react-app custom-hook-demo
```
Go make some ☕, because it's gonna take a while now.🥲

Run the server
```
npm start
```

Clean up the App.js file, so it looks like this,
```react
// App.js

import './App.css';

function App() {
  return (
    <div className="App">
      <h1>Hello</h1>
    </div>
  );
}

export default App;
```

This will render a page with "Hello" as the heading.

Copy-paste this style in your App.css file.

```css
/* App.css */

.App {
  text-align: center;
  width: 70%;
  margin: auto;
}

header {
  min-height: 20vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: 100px;
  color: white;
  margin-bottom: 50px;
}

.joke {
  background-color: #282c34;
  padding: 40px;
}

.new_joke {
  float: right;
  padding: 10px;
  font-size: 20px;
  margin-top: 20px;
  color: #282c34;
}

.new_joke:hover {
  cursor: pointer;
}

.joke p{
  padding: 0;
  font-size: x-large;
  line-height: 35px;
}
```

Now we will be creating our useFetchJoke hook.
Create a new file named useFetchJoke.js

```react
// useFetchJoke

import { useEffect, useState } from "react";

export default function useFetchJoke() {
	const [joke, setJoke] = useState('');

	useEffect(() => {
		getNewJoke();
	}, [])

	async function getNewJoke() {
		setJoke('Loading...')
		const res = await fetch('https://icanhazdadjoke.com/', {
			headers: {
				Accept: 'application/json'
			}
		});
		const data = await res.json();
		setJoke(data.joke);
	}

	return [joke, getNewJoke];
}
```
So first we have a state named **joke**, which stores the actual joke string in it. The function **setJoke** is used to update this particular state.

Then we have a built-in hook called **useEffect** (yes, you can use built-in hooks or even another custom hook inside of a custom hook).
useEffect contains a function and a list of dependencies. The dependency list contains a list of states and functions, when any of the state is changed the function present in useEffect is executed. If the dependency list is empty (as it is in our case) the function is executed only once when the component is first mounted. 
What if we don't pass a dependency array ? console log something in your function and try it for yourself. 😉

We have a function called **getNewJoke()**, as you might have guessed it, it's the actual function which fetches a new joke from the api.
Before requesting for a new joke from the api, we set the joke state to loading, this will print "**loading..**" instead of a joke on the screen, so the user will know that a new joke is being fetched.
We request a new joke from the icanhazdadjoke api, and set the **joke** state to the newly fetched joke, using **setJoke** function.

After all this, we return 2 things, our **joke** state and **getNewJoke** function.

So, here's the flow ( read it slowly), the **joke** state we just returned will be rendered in our component and when we click the "get new joke" button, **getNewJoke** function will be trigerred, which will fetch a joke and update our state, which will be reflected on the DOM.

```react
// App.js
import './App.css'
import useFetchJoke from './useFetchJoke';

function App() {

  const [joke, getNewJoke] = useFetchJoke();
  
  return (
    <div className="App">
      <header>Custom Hook</header>
      <div className='joke'>
        <p>{joke}</p>
      </div>
      <button className='new_joke' onClick={getNewJoke}>Get a new one !!</button>
    </div>
  );
}

export default App;

```

First of all, we called the **useFetch** hook, which returned us the **joke** state and a function to get a new joke.
As we can see inside the paragraph tag we are rendering the joke and when the button is clicked, we are calling the **getNewJoke** function.

If you made it this far, then congratulations and thanks a lot. 😁
PS: This is actually my first post, and to be honest, writing takes up a lot of brain cells. I had a really hard time figuring out what to write, how to write etc..
Any feedback will be appreciated.