Important Custom React Hooks - (Part 1)
Tags: react, webdev, javascript
Published: 2021-06-19 15:56:55

It’s been a while since React hooks were released, and everyone has fallen in love with them. I understand because I’m one of you too. Hooks got me hooked!.

Welcome everybody in this two part series of articles. Where we are gonna create a some custom react hooks to increase features as well as productivity of your react app.

Here's the list of hooks we are going to create a in these two parts:

*Part 1 :*
* `use-window-dimensions`(for getting window's width and height)
* `use-outside-click`(for detecting outside click from a element)

*Part 2:*
* `use-window-positions`(for detecting window's position)
* `use-scroll-direction`(for detecting scroll(up or down)) 

So before we get started for those who don't know what React and React hooks are? let's have brief introduction for them.

> ## Prerequisites.
> * Basic understanding of Javascript and DOM.
> * Basic understanding of React and React Hooks.


## Project Setup

Now let's back to our main agenda.

First we are going new **React App** with `create-react-app`. I'd call it custom-react-hooks.

So, open terminal and run the following command.

```bash
npx create-react-app custom-react-hooks
```
Open project in favorite IDE/Text-Editor.In  this tutorial I am using VSCode.

After that, go to `src` folder and create a new folder call `hooks`. 

Till now, our `react-app` should look like this.

![Vs code folder structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yqbmruzl8clg6tu4o0k2.png)

Now, clean `src/App.js` file like this:
```jsx

import React from 'react';
import "./App.css";

const App = () => {
    return <div>Hello, let's start coding are custom hooks.</div>;
};

export default App;
```
You can also delete `src/App.test.js`, `src/setuptest.js`, `src/logo.svg`. I am gonna do so.

Now, that's enough. let's start coding our first **custom-react-hooks**

## 1.`use-window-dimensions`:

In `src/hooks` folder I'll make a new file called `use-window-dimensions.js`. This is the file where we'll create our `use-window-dimensions` hook.

```jsx
import { useState, useEffect } from "react";



const getDimensions  = () => {
    const { innerWidth : width, innerHeight : height } = window;

    return { width, height }
}

const useWindowDimensions = () => {
    const [windowDimensions,setWindowDimensions] = useState(getDimensions());


    useEffect( () => {

        function handleResize(){
            setWindowDimensions(getDimensions());
        }

        window.addEventListener("resize", handleResize)
        return ( () => { window.removeEventListener("resize", handleResize) } )
    } ,[])

    return windowDimensions
}

export default useWindowDimensions;
``` 
Now let's break the code down :

* `getDimensions()` function is simply returning window's width and height.
* `useWindowDimensions()` function is our hook that will return window dimensions.
* In `useWindowDimensions()` functions we've first store window's dimensions in the state.
* Next we run a `useEffect` hook to change our state(dimensions) whenever `resize` event hired on window.
* And then in our hook we are returning window's height and width.

### Testing our hook.

We are going to test our hooks in `App.js`.

```jsx
import React from "react";
import "./App.css";
import useWindowDimensions from "./hooks/use-window-dimensions";

const App = () => {
    const { width, height } = useWindowDimensions();

    return (
        <div>
            <h1># First custom hook:</h1>
            <p>
                Window's width is {width} and height is{height}
            </p>
        </div>
    );
};

export default App;
```
Run dev server on localhost: 

```bash
npm start
```
OR

```bash
yarn start
```

Now you outputs should like this:

![first-hook-output-1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k879atq2c21xr2dqohf1.png)

![first-hook-output-2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m3b9eyliyhefxtspfeg2.png)

![first-hook-output-3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a9hj2378y04wg7t053dh.png)

And that it. 
👍 Awesome! we made it.

Now let's move to the next hook.

## 2. `use-outside-click`

Like what we've done before create a new file in `src/hooks` folder called `use-outside-click.js`

```jsx

import  { useEffect } from "react";

export default function useOutsideClick(ref,onClick) {
    useEffect(() => {
        if(!ref) return;
        function handleClickOutside(event) {
            if (ref.current && !ref.current.contains(event.target)) {
                onClick(event);
            }
        }

        document.addEventListener("mousedown", handleClickOutside);
        return () => {
            document.removeEventListener("mousedown", handleClickOutside);
        };
    }, [ref,onClick]);
}

```
* `useOutsideClick` is hook which is taking two arguments first `ref` of element on which we want to detect outside click and second a function that will run when it detect outside click from element. 

* on every `mousedown` event we check whether the area we clicked on contains targeted element or not. If it contains we   are running a function that we'll pass in hook as second argument.

### Let's test it.

In `src/App.js`, let's check whether it's working or not.

```jsx
import React, { useRef } from "react";
import useOutsideClick from "./hooks/use-outside-click";
import "./App.css";

const App = () => {
	const boxRef = useRef(null);

	useOutsideClick(boxRef, () => {
		console.log("clicked detected outside the box");
	});

	return (
		<div className='app'>
			<div
				ref={boxRef}
				className='box'
				style={{
					width: "200px",
					height: "200px",
					backgroundColor: "lightgreen"
				}}
			>
				Hi, I am the box.
			</div>
		</div>
	);
};

export default App;
```

And when we clicked outside the green box the it should logged in console as following :

![second-hook-output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dzjy0ir14kd7z9ewigoc.png)


Amazing 😲, it's working.

 > *Part 2 (coming soon)*

Happy coding 😍.