Implementing a Simple Modal Component in React

Cameron Moorehead

​ Modals are one of the most ubiquitous UI elements on the web. In this post we’re going to implement a basic modal component in React. ​ Here’s a summary of the steps we’ll take:

  • Create a Dashboard component which holds state and an open button
  • Create a Modal component which renders children and holds a close button
  • Display the Modal component upon clicking open
  • Close the Modal component upon clicking close

Let’s begin with getting our Dashboard component to render with the following code:

import React, { Component } from "react";
import ReactDOM from "react-dom";

class Dashboard extends Component {
  state = { show: false };

  showModal = () => {
    this.setState({ show: true });
  };

  hideModal = () => {
    this.setState({ show: false });
  };

  render() {
    return (
      <main>
        <h1>React Modal</h1>
        <button type="button" onClick={this.showModal}>
          open
        </button>
      </main>
    );
  }
}

const container = document.createElement("div");
document.body.appendChild(container);
ReactDOM.render(<Dashboard />, container);

Nothing new to see here. We’re simply creating a Dashboard component which has a show state. This state is togglable via the showModal and hideModal class properties, for which each will have their own button. In the example above, the Dashboard button’s onClick handler will toggle the show state to true.


​ Next, we’ll build out the Modal component: ​

Modal.js

const Modal = ({ handleClose, show, children }) => {
  const showHideClassName = show ? "modal display-block" : "modal display-none";

  return (
    <div className={showHideClassname}>
      <section className="modal-main">
        {children}
        <button onClick={handleClose}>close</button>
      </section>
    </div>
  );
};

Here things get a little bit more involved. The Modal component we’ve built will receive handleClose, show, and children down as props from *Dashboard. There’s a showHideClassName variable which will either display the Modal or not by means of checking the value of show. If show is true, the top level div JSX element will have a showHideClassname of modal display-block, otherwise, it will be modal display-none.

We are also rendering the children of Modal, and setting up a close button, which has the onClick handler of handleClose, which will set show in Dashboard to false.


We’ll need to incorporate this Modal component in the Dashboard component like so:

import React, { Component } from "react";
import ReactDOM from "react-dom";

class Dashboard extends Component {
  state = { show: false };

  showModal = () => {
    this.setState({ show: true });
  };

  hideModal = () => {
    this.setState({ show: false });
  };

  render() {
    return (
      <main>
        <h1>React Modal</h1>
        <Modal show={this.state.show} handleClose={this.hideModal}>
          <p>Modal</p>
          <p>Data</p>
        </Modal>
        <button type="button" onClick={this.showModal}>
          open
        </button>
      </main>
    );
  }
}

const container = document.createElement("div");
document.body.appendChild(container);
ReactDOM.render(<Dashboard />, container);

All we’ve done is added Modal into the Dashboard component’s render method and passed down show and handleClose as props. Additionally there are now a couple of paragraph tags which will exist on the Modal’s this.props.children property.

With this, we have everything we need to style things up to have a functional modal:

.modal {
  position: fixed;
  top: 0;
  left: 0;
  width:100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.6);
}

.modal-main {
  position:fixed;
  background: white;
  width: 80%;
  height: auto;
  top:50%;
  left:50%;
  transform: translate(-50%,-50%);
}

.display-block {
  display: block;
}

.display-none {
  display: none;
}

All it does is create a center-aligned white box with a black background after its alpha levels have been adjusted for transparency.

Note that our Modal component is very basic and doesn't offer any affordances for accessibility (a11y). We will revisit and build upon this component in a future post.

Here's what our Modal looks like in action:

Our simple modal in action

And here's a working Codepen demo.

  Tweet It

🕵 Search Results

🔎 Searching...