How to Implement a Modal Component with React
Tags: react, javascript, tutorial, frontend
Published: 2023-05-25 14:42:46

## **OUTLINE**

- Introduction
- Prerequisite
- Setting your react project with Vite
- Step-by-step process on how to implement a modal component with React

---

## **Introduction**

In this article, we'll walk through the process of implementing a modal component with React. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wk0aj32rqu1muwfei671.gif)

The above image shows the user interface (UI) of the project we would be working on. The UI displays a couple of profile cards and each profile card represents a person with their name and profile picture, while the modal component displays additional information about each selected profile, including their name, role, skills, and profile picture.

Let's get started!

---

## **Prerequisite**

Before starting, ensure that Node.js and NPM are installed on your system. You can check if you have these installed by running the following commands in your terminal:

```react
node -v
npm -v
```

If you do not have these packages installed on your computer, download and install Node.js from the official website.

Also, a basic knowledge of JavaScript and React is needed.

## **Setting your React project with Vite**

Follow the process outlined in this blog post Setting your [React project with Vite](https://dev.to/adetutu/setting-up-a-react-project-with-vite-a-step-by-step-guide-329k) to create a new React project.

In the new React project, remove the pre-existing code and styles in the `index.css`, `App.jsx`, and `App.css` files.

---

## **Step-by-step process on how to implement a modal component with React**

---

## **STEP 1: Import packages and files**

Inside the project directory, navigate to the App.jsx file and import the necessary package and file.

```react
import { useState } from 'react';
import './App.css';
```

This imports the useState hook from the 'react' package, which allows you to use state in functional components. It also imports the 'App.css' file for styling.

Within the `src` directory, create a `components` folder and add the following files along with their corresponding CSS files: `card.jsx`, `modal.jsx`, `card.css`, and `modal.css`.

```react
 src/
│  components/
     │  Card/
          Card.jsx
          Card.css
     │  Modal/
          Modal.jsx
          Modal.css
│  App.css/
│  App.jsx/
│  index.css/
│  main.jsx/ 

```
---

## **STEP 2: Create the App component**

In this next step, create a functional component named `App` and initialize a state variable using the `useState` hook and import the `App.css` file, which contains CSS styles for the `App` component. We also import the `Card` component from the `./components/card/card` file.


```react
import { useState } from 'react';
import './App.css';
import Card from './components/card/card';

const App = () => {

 const [profiles, updateProfiles] = useState([
            { id: 1, name: "Sophia Anderson", role: "Frontend Engineer", skills: ["HTML", "CSS", "JavaScript", "React", "Next.js"], profilePic: "https://rb.gy/9jh39" },
            { id: 2, name: "Isabella Sullivan", role: "Senior Java Developer", skills: ["Java", "Spring Boot", "Spring Framework", "Maven"], profilePic: "https://rb.gy/gs5lt" },
            { id: 3, name: "Ava Reynolds", role: "Backend Developer", skills: ["Node.js", "Express", "MongoDB", "Nest.js"], profilePic: "https://rb.gy/rs32e" },
            { id: 4, name: "Olivia Thompson", role: "Blockchain Developer", skills: ["Web3", "JavaScript", "Solidity", "Rust", "Smart contracts"], profilePic: "https://rb.gy/xbjed"},    
  ])

return (
  <div className='App'>
      <div className='profile-card'>

        {profiles.map(profile =>{
                return(< Card 
                  key={profile.id} 
                  id={profile.id} 
                  name={profile.name} 
                  skills={profile.skills} 
                  role={profile.role} 
                  profilePic={profile.profilePic} 
                  />)
         })}

      </div>
  </div>
);
};

```

## **Code explanation**

We declare a state variable called `profiles` and `updateProfiles` to update the state. The `profiles` state variable contains an array of user/profile objects with various properties such as `id`, `name`, `role`, `skills`, and `profilePic`.

We declare a return statement that returns the JSX code that will be rendered to the DOM.

Next, we use the `.map()` function on the `profiles` array which iterates over each `profile` object in the array and returns a `<Card/>` component for each profile. The properties of the profile object (such as id, name, skills, role, and profilePic) are passed as props to the `<Card/>` component.


> _It is important to pass a key prop `key={profile.id}` to the card component within the `profiles.map` function. This is because the key prop value will be used as a unique identifier for each profile in the `profiles` array._


> _In React, the key prop is not accessible within the component but it is primarily used by React to update the list and maintain the state and order of the component._

---

## **STEP 3: Style the App component**

Add the CSS styles below to your `App.css` file to style the App component.

```react
.App {
    text-align: center;
    margin: 10rem 3rem;
  } 
  
.profile-card{
    display: flex;
    flex-direction: row;
    justify-content: space-around;
    margin-top: 4rem;
}

```
---

## **STEP 4: Create the card component**

In this step, we create a functional component named `Card` and initialize a state variable using the `useState` hook and import the `Card.css` file, which contains CSS styles for the Card component.

```react
import './Card.css'
import Modal from '../Modal/Modal';
import { useState } from 'react';

const Card = ({id, name, profilePic, skills, role}) => { 

const [showModal, setShowModal] = useState(false)

const handleClose = () => {setShowModal(false)}

  return (
    <>  
        <div className="card">
            <div className="number">{id}</div> 
            <div>
                <img className="profile-pic" src={profilePic} alt="profile picture" />
            </div>
            <div className="descr">
                <p className="name">{name}</p>
                <button className="learn-more" onClick={() => setShowModal(true)}>Click to learn more</button>
            </div>
        </div>
 
         {showModal && <Modal name={name} role={role} skills={skills} profilePic={profilePic} handleClose={handleClose}/>}
    </>
  );
};

export default Card;

```

## **Code explanation**

Firstly, we declare a new component called `card` using the arrow function expression. In the previous step, the card component received an object of props as an argument. We use destructuring to extract some properties (id, name, profilePic, skills, and role) from the props object.

```react
const [showModal, setShowModal] = useState(false)

const handleClose = () => {setShowModal(false)}
```

In the card component, we declare a state variable called `showModal` and `setShowModal` to update the state. The initial value of `showModal` is set to `false` to hide the modal. We declare a function named `handleClose` that sets the `showModal` state to `false`, which closes the modal when it is called.

We declare the return statement and then we pass each of the prop values into the JSX element so each profile card can be rendered to the DOM. 

```react
<button className="learn-more" onClick={() => setShowModal(true)}>Click to learn more</button>

```

Next, We pass an `onClick` event to the `learn more` button in the card component. When the button is clicked, it triggers an `onClick` event that calls the `setShowModal` function with `true` as the argument. This updates the `showModal` state and shows the modal.

```react
{showModal && <Modal name={name} role={role} skills={skills} profilePic={profilePic} handleClose={handleClose}/>

```

Finally, we import the modal component from the modal directory and render the modal component in the card component. The modal component is only rendered if `showModal` is true, and we pass in various props such as `name`, `role`, `skills`, `profilePic`, and the `handleClose` function to the modal component. When the modal is rendered, the `handleClose` function is passed as a prop to handle its close action.

---

## **STEP 5: Style the card component**

Add the CSS styles below to your `Card.css` file to style the card component.

```react
.card {
    border: 1px solid rgba(0, 0, 0, 0.175);
    border-radius: 10px;
  }
  
  .number{
    text-align: right;
    font-size: 1.5rem;
    font-weight: 700;
    padding: 0.8rem;
  }
  
  .name{
    font-size: 1.8rem;
    font-weight: 600;
  }
  
  .profile-pic{
    width: 100%;
    height: 300px;
  }
  
  .descr{
    margin-bottom: 1.5rem;
  }
  
  .learn-more{
    padding: 0.8rem;
    outline: none;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    font-size: 1.5rem;
  }
  
  .learn-more:hover{
    background-color: #6a6d6d;
    color: #ffff;
  }
  
  @media screen and (max-width: 1400px) {  
    .profile-card{
      display: flex;
      flex-direction: column;
      margin-top: 1rem;
    }
  
    .card{
      margin-top: 3rem;
    }
  }

```
---

## **STEP 6: Create the modal component**

In this next step, we create a functional component named `Modal` and import the `Modal.css` file, which contains CSS styles for the Modal component.

```react
import './Modal.css' 

const Modal = ({name, profilePic, handleClose, skills, role}) => {
  
  return (
    <div className="modal-backdrop">

        <div className="modal">
            <img className="modal-img" src={profilePic} alt="profile pic" />
            <div className="modal-body">
               <div className='modal-name'>{name}</div>
               <div className='modal-role'>{role}</div>
               <div className="skills">
               <ul>
                    {skills.map(skill => <li key={skill}>{skill}</li>)}
               </ul>
               </div>
            </div>
            <button className="close-btn" onClick={()=> handleClose()}>Close</button>
        </div>

    </div>
  );
};

export default Modal;
```

## **Code explanation**

We declare a new component called ‘modal’ using the arrow function expression. In the previous step, the card component received an object of props as an argument. Then, we destructure the specific props such as `name`, `profilePic`, `handleClose`, `skills`, and `role` from the props object.

We declare the return statement and then we pass each of the prop values into the JSX elements to be rendered.

```react
{skills.map(skill => <li key={skill}>{skill}</li>)}

```

The `skills` prop value consists of a list of `skills` arrays. So we use the map function to iterate over the `skills` array. It returns a new array of list items `<li>` with each skill as its content. The key attribute is set to the skill for proper identification of list items.

```react
<button className="close-btn" onClick={()=> handleClose()}>Close</button> 

```

Lastly, we pass an `onClick` event to the close button in the modal component. When the button is clicked, it triggers the `onClick` event that calls the `handleClose` function, which was passed as a prop to handle the closing action of the modal.

---

## **STEP 7: Style the modal component**

Add the CSS styles below to your `Modal.css` file to style the modal component.

```react
.modal-backdrop {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0,0,0,0.8);
  }

.modal { 
    max-width: 480px;
    height: 400px;
    margin: 150px auto;
    background-color: #ffff;
    border-radius: 10px;
    padding: 0;
  }

.modal-img{
    border-radius: 50%;
    height: 100px;
    width: 100px;
    margin: 4rem 0 2rem;
}

.modal-name {
    font-size: 2rem;
    font-weight: 600;
}

.modal-role{
    font-size: 1.5rem;
    font-weight: 600;
    margin-top: 1.5rem;
    font-style: italic;
}

.skills ul {
    display: flex;
    padding: 0;
    justify-content: center;
    margin-top: 0;
  }

.skills li {
    list-style-type: none;
    margin-right: 10px;
    color: black;
    background-color: #ebebf2;
    padding: 0.5rem 1rem;
    margin: 2rem 0.5rem;
    font-size: 1.3rem;
    border-radius: 5px;
    font-weight: 600;
}

.close-btn{
    background-color: #ebebf2;
    border-radius: 3px;
    cursor: pointer;
    font-size: 1.5rem;
    padding: 1rem 2rem;
    margin-top: 2rem;
    outline: none;
    border: none;
    font-weight: 500;
    text-transform: uppercase;
  }
  
  .close-btn:hover,
  .close-btn:focus{
    background-color: #9393B2;
    color: #ffff;
  }

  @media screen and (max-width: 480px) { 
    .skills li {
        padding: 0.5rem 0.8rem;
        margin: 2rem 0.4rem;
        font-size: 1rem;
    }
  }

```
---

We have successfully implemented a modal component with React and you can find the complete code for this tutorial on [GitHub](https://github.com/adetutudeborah/react-modal-component) and the [live link](https://react-modal-component-six.vercel.app/).