How to Create a Pop-Up Modal in React
Tags: react, javascript, beginners, tutorial
Published: 2022-08-23 17:22:00

## What is a modal?
A modal is a box that appears on the page, blocking all functions to concentrate focus on a particular action. This is their differentiating feature, they ask the user to perform an action.
To return to the main content, the user must engage with the modal by completing an action or by closing it.

## Let's create a modal with React
Code on GitHub: https://github.com/nicvazquez/react-modal
Demo: https://react-modal-nicvazquez.vercel.app/

### Step 1: Create App
Let's create the React app with Vite using the following command:
```
npm create vite@latest
```
After this, it will ask us to complete with some options:
```
√ Project name: ... react-modal
√ Select a framework: » react
√ Select a variant: » react
```

Excellent! Now run the following commands:
```
cd react-modal
npm install
npm run dev
```

If everything went well, you should have the application created, with the dependencies installed and have the project running on a local server, which in my case is http://127.0.0.1:5173/.
![Vite running React app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w49308jgkakd1b3faw8l.png)


### Step 2: Let's create the base of our application

- Open **App.jsx** and create the button element.
Your code should look like this:
```jsx
import "./App.css";

function App() {
	return (
		<div className="container">
			<button>Open Modal</button>
		</div>
	);
}

export default App;
```

- Modify the **App.css** file. The styles should look like this:
```css
.container {
	display: grid;
	place-items: center;
	width: 100%;
	height: 100vh;
}
```
- Now modify **index.css**:
```css
:root {
	font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
	color-scheme: light dark;
	color: rgba(255, 255, 255, 0.87);
	background-color: #242424;
}

button {
	border-radius: 8px;
	border: 1px solid transparent;
	padding: 0.6em 1.2em;
	font-size: 1em;
	font-weight: 500;
	font-family: inherit;
	background-color: #1a1a1a;
	cursor: pointer;
	transition: border-color 0.25s;
}
button:hover {
	border-color: #646cff;
}
button:focus,
button:focus-visible {
	outline: 4px auto -webkit-focus-ring-color;
}

@media (prefers-color-scheme: light) {
	button {
		background-color: #f9f9f9;
	}
}
```

If we go to our local server, we should have the following:

![Local server image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a9ykf4icvubc58t9zy3a.png)

### Step 3: Let's create the modal
- In the `src` folder, let's create the `components` folder and inside it we need to create another folder called `Modal`, which should contain the `Modal.jsx` and `modal.module.css` files.

The structure of our project should look something like this:
```
REACT-MODAL
└─── node_modules
└─── public    
│
└─── src
│   │
│   └─── assets
│   |       react.svg
│   └─── components \ Modal
│   |        Modal.jsx
│   |        modal.module.css
|   |   App.css
|   |   App.jsx
|   |   index.css
|   |   main.jsx
│   
|   .gitignore
|   index.html
|   package-lock.json
|   package.json
|   vite.config.js
```

- To give structure to the modal, we must add the HTML to it in `Modal.jsx`:
```jsx
import React from "react";
import styles from "./modal.module.css";

export const Modal = () => {
	return (
		<div className={styles.modalBack}>
			<div className={styles.modalContainer}>
				<div>
					<h2>Modal</h2>
					<p>
						Lorem ipsum dolor sit amet consectetur adipisicing elit. Ex, nisi. Dolorem est
						esse iste perferendis.
					</p>
				</div>
				<button className={styles.modal__closeBtn}>Close</button>
			</div>
		</div>
	);
};
```

- To style the modal, we must have this code in `modal.module.css`:
```css
.modalBack {
	position: absolute;
	height: 100vh;
	width: 100%;
	display: grid;
	place-items: center;
	background-color: rgba(0, 0, 0, 0.322);
}

.modalContainer {
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	align-items: flex-start;
	height: 30%;
	max-width: 60%;
	background-color: rgb(39, 43, 114);
	padding: 3rem;
	border-radius: 5px;
}
```

- Let's go to **App.jsx** and import the Modal
```jsx
import "./App.css";
import { Modal } from "./components/Modal/Modal";

function App() {
	return (
		<div className="container">
			<button>Open Modal</button>
			<Modal />
		</div>
	);
}

export default App;
```

Your modal should look like this:

![Modal in Local Server](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h1br853cwejvx7mv2pcf.png)

So far so good, but one thing is missing... show the modal when the user clicks on the button.
Let's get to it!

### Step 4: Being able to open the modal
- Go to **App.jsx** and import `useState`:
```jsx
import { useState } from "react";
```

- Let's declare the useState with the default value `false`:
```jsx
const [showModal, setShowModal] = useState(false)
```

- Let's add the onClick function and the conditional to display the modal:
```jsx
<button onClick={() => setShowModal(true)}>Open Modal</button>
{showModal && <Modal />}
```

- Our **App.jsx** should look like this:
```jsx
import { useState } from "react";
import "./App.css";
import { Modal } from "./components/Modal/Modal";

function App() {
	const [showModal, setShowModal] = useState(false);
	return (
		<div className="container">
			<button onClick={() => setShowModal(true)}>Open Modal</button>
			{showModal && <Modal />}
		</div>
	);
}

export default App;
```

Now if we click the button, the modal should appear. We are doing well, but we still need to close the modal

### Step 5: Being able to close the modal
- We must go to the **Modal.jsx** file and pass a prop as a parameter to close the modal.
```jsx
export const Modal = ({ closeModal }) => {
```

- Put that prop as onClick event to the button of the modal:
```jsx
<button onClick={closeModal} className={styles.modal__closeBtn}>
	Close Modal
</button>
```

- If we want also to close the modal when clicked outside of it, we can pass the prop to the parent div
```jsx
<div onClick={closeModal} className={styles.modalBack}>
```

- Our `Modal.jsx` should look like this:
```jsx
import React from "react";
import styles from "./modal.module.css";

export const Modal = ({ closeModal }) => {
	return (
		<div onClick={closeModal} className={styles.modalBack}>
			<div className={styles.modalContainer}>
				<div>
					<h2>Modal</h2>
					<p>
						Lorem ipsum dolor sit amet consectetur adipisicing elit. Ex, nisi. Dolorem est
						esse iste perferendis.
					</p>
				</div>
				<button onClick={closeModal} className={styles.modal__closeBtn}>
					Close Modal
				</button>
			</div>
		</div>
	);
};
```

- Now we need to send the function as props from App.jsx for the onClick event to work
```jsx
{showModal && <Modal closeModal={() => setShowModal(false)} />}
```

- Our `App.jsx` should finally look like this:
```jsx
import { useEffect, useState } from "react";
import "./App.css";
import { Modal } from "./components/Modal/Modal";

function App() {
	const [showModal, setShowModal] = useState(false);

	return (
		<div className="container">
			<button onClick={() => setShowModal(true)}>Open Modal</button>

			{showModal && <Modal closeModal={() => setShowModal(false)} />}
		</div>
	);
}

export default App;
```

### Done! :-)
That was it! I hope this post has been very helpful to you. Any questions or suggestions leave it in the comments.

You can see the code on GitHub: https://github.com/nicvazquez/react-modal
Demo: https://react-modal-nicvazquez.vercel.app/