# Creating a React Modal with React custom Hooks and Typescript

Hello Guys,

React hooks are very useful features of React and with this comes custom React hooks, these custom React hooks have endless possibilities and can easily replace container Logic in Container/Presentational Model.

Read more about that here [Patter.dev](https://www.patterns.dev/posts/#design-patterns)

# Creating the Modal from Scratch 

## Creating the Presentational Part of Modal

Let's create the presentational part of the  Modal in this I will be quick and just show you the code 


```
import React, { ReactNode } from "react";


interface ModalType {
  children?: ReactNode;
  isOpen: boolean;
  toggle: () => void;
}

export default function Modal(props: ModalType) {
  return (
    <>
        <div className="modal-overlay" >
          <div  className="modal-box">
            {props.children}
          </div>
        </div>
    </>
  );
}
 

```


let me explain this to you, So here we have two div an `overlay-div` which have full width and height, and a `modal-box div`. 
 
So we are trying to achieve something like below where if the user clicks anywhere else than the `modal-box div` the modal will get closed. And all the modal content will be inside the white part of the modal.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1659644607856/IjCMklBHB.png align="left")


let's quickly set up the CSS for our modal divs.

```

.modal-overlay {
  z-index: 9999;
  width: 100vw;
  height: 100vh;
  position: absolute;
  top: 0;
  background: rgba(0, 0, 0, 0.7);
  display: flex;
  justify-content: center;
  align-items: center;
}

.modal-box {
  display: block;
  background: white;
  width: 70%;
  height: 70%;
  padding: 1rem;
  border-radius: 1rem;
}

```

once this is done we need will get to our logic part where we will only render the Modal if our state is true. 

## Why custom Hook?

Here I used a custom hook so that I don't have to write the same logic again and again when trying to use modal and add the same function in all the files.

## Adding logic to the Hooks 

let's quickly make a new file `useModal.tsx` in our `hooks` folder this will be a pure function and only contain the logic for now.


```
// useModal.tsx

import { useState } from "react";

export default function useModal() {
  const [isOpen, setisOpen] = useState(false);

  const toggle = () => {
    setisOpen(!isOpen);
  };

  return {
    isOpen,
    toggle
  };
}

```

In this, we have a state `isOpen` to show or hide the modal, and then there is a function that actually toggles the visibility of the Modal.

now let's use this code in our `App.tsx` and implement a Modal that gets triggered on click

## Combining the logic and Presentational Part ( hooks + Modal component)

### Calling the Modal component and useModal

let's import out the Modal component and `useModal` hook in `App.tsx` 

```
import Modal from "./component/modal";
import useModal from "../src/hooks/useModal";
```

let's add the other logic and pass `isOpen` and `toggle` to the `Modal` component.

our `App.tsx` will look something like below

```
export default function App() {
  const { isOpen, toggle } = useModal();
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <button onClick={toggle}>Open Modal </button>
      <Modal isOpen={isOpen} toggle={toggle}></Modal>
    </div>
  );
}

```


### Adding Logic to Modal component

Well at this point we are almost done all we need is to add some basic conditional rendering logic to our Modal component and let's see what we have.


```
// Modal.tsx

import React, { ReactNode } from "react";

interface ModalType {
  children?: ReactNode;
  isOpen: boolean;
  toggle: () => void;
}

export default function Modal(props: ModalType) {
  return (
    <>
      {props.isOpen && (
        <div className="modal-overlay" onClick={props.toggle}>
          <div  className="modal-box">
            {props.children}
          </div>
        </div>
      )}
    </>
  );
}

```

we added the onClick event and passed the `toggle` function to it so that if we click anywhere else on the outside of the modal, the modal get's close.

Also, we rendered our component such that if `isOpen = false ` it will return nothing.

At this point we are done let's see how it looks now.



![CPT2208050212-632x542.gif](https://cdn.hashnode.com/res/hashnode/image/upload/v1659645825205/PyuaqONbo.gif align="left")

Now it's working fine .......... Well Almost actually.

if you noticed if we click on the inner div even then the whole modal is getting close which is not something we can do as this can lead to several issues. 

This is happening due to the phenomenon called Event Bubbling in Javascript where any event is propagated through the parent divs.

# Solving bugs and handling Event Propagation.

In React this can be easily solved by the using `event.stopPropagation()` method which is already provided by React.

We will just call this method when the user clicks on the Inner div.

let's see how our code looks now

```
// Modal.tsx

import React, { ReactNode } from "react";

interface ModalType {
  children?: ReactNode;
  isOpen: boolean;
  toggle: () => void;
}

export default function Modal(props: ModalType) {
  return (
    <>
      {props.isOpen && (
        <div className="modal-overlay" onClick={props.toggle}>
          <div onClick={(e) => e.stopPropagation()} className="modal-box">
            {props.children}
          </div>
        </div>
      )}
    </>
  );
}

```

Yaay !!!!!!!!!! now the above problem is solved


# Try this on Sandbox?

<iframe src="https://codesandbox.io/embed/modal-using-react-hooks-2jn08i?fontsize=14&hidenavigation=1&theme=dark"
     style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
     title="Modal Using React Hooks"
     allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking"
     sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
   ></iframe>


Hope you like testing it try adding more features to it.


# TL;DR


- We learned about container/presentational design patter
- We learned how to create our own custom hooks and separate all the logic parts from the UI.
- We learned how the Modal component works and to create reusable React component
- We learned what is event propagation and how to stop it.




if you like this post let's get connected on Twitter:

 [Follow me here](https://twitter.com/theysaymaurya)






