Functional modal component in Reactjs

In this tutorial, we will see how to create a modal as a functional component in Reactjs.

We have already seen how to create a modal as a class component. This is an improved version of the same with minimal props and code.

Functional modal component in Reactjs

Modal component’s layout

A modal is a popup that is fixed on the screen and center-aligned both vertically and horizontally, that is used to show details of anything.

Our modal will accept a title, and a children component, show a flag that will make the component visible, and an on-close event handler that will trigger when the modal closes.

const Modal = ({ children, show, onClose, title }) => {
  return (
    show && (
      <>
        <div className="modal-backdrop" onClick={onClose} />
        <div className="modal-wrapper">
          <div className="modal-content">
            <div className="modal-header">
              <div className="modal-title">{title}</div>
              <div onClick={onClose} className="modal-close">
                X
              </div>
            </div>
            <div className="modal-body">{children}</div>
          </div>
        </div>
      </>
    )
  );
};

As you can see we also have a backdrop before the modal, which is the background of the modal on whose click we close the modal, Basically modal will be closed if clicked anywhere outside its area.

Styling the modal

The modal and the backdrop are both fixed positions in the viewport, the backdrop covers the whole viewport and is behind the modal, while the modal takes a specific dimension on the screen.

.modal-backdrop {
  position: fixed;
  width: 100vw;
  height: 100vh;
  background-color: rgba(0, 0, 0, 0.2);
  top: 0;
  left: 0;
}

.modal-wrapper {
  padding: 10px;
  margin: 10px auto;
  box-shadow: 0px 2px 6px #000;
  position: fixed;
  width: 100%;
  max-width: 500px;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 11111;
  background-color: #fff;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}

.modal-close {
  text-align: center;
  font-size: 1.2em;
  cursor: pointer;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background-color: gray;
  line-height: 1.7em;
  color: #fff;
}

Animating the modal on mount

We can also add the animation to the modal like it is sliding from the top by adding an active class to the modal-wrapper

@keyframes slide {
  from {
    transform: translate(-50%, -100%);
  }
  to {
    transform: translate(-50%, -50%);
  }
}

.modal-wrapper.active {
  animation-name: slide;
  animation-duration: 0.35s;
}
<div className={`modal-wrapper ${show ? "active" : ""}`}>

Rendering the modal

Now all we have to do is control the state to show-hide the modal from the parent component.

We will create an on-close handler that will hide the modal (update the parent state) in case the close button is clicked or clicked on the backdrop.

import { useState } from "react";

const App = () => {
  const [show, setShow] = useState(false);

  return (
    <div>
      <button onClick={() => setShow(true)}>
        {show ? "hide" : "show"} modal
      </button>
      <Modal show={show} onClose={() => setShow(false)} title="Modal">
        <h1>Learnersbucket</h1>
      </Modal>
    </div>
  );
};