DEV Community

Atauba Prince
Atauba Prince

Posted on

Building a modal in React.

In this tutorial, we are going to build a modal in React. Below is a demo of it.

Prerequisites

These are the prerequisites required to follow this tutorial.

  • Knowledge of React (You should have at least a basic understanding of state and props).

  • An installation of Node JS on your PC.

  • create-react-app installed on your PC.

Initial Setup

Initialize the project by running the command below in the root directory of your project, it installs the libraries and tools needed to start the project.

create-react-app basic-modal
Enter fullscreen mode Exit fullscreen mode

Building the Components

Before creating the components or writing any code, follow the steps below to delete unwanted files and also create the files needed for the project.

  1. Delete the following files: app.css, app.test.js, logo.svg and registerServiceWorker.js from the src folder.

  2. Create a folder in the src directory and name it components.

  3. In the components folder, create another folder called Modal.

  4. In the Modal folder, create two files namely Modal.js and Modal.css.

After doing this, your project structure should be similar to this:

Modal.js

Open the Modal.js file in the components folder and add the following code.

import React from 'react';

import './Modal.css';

const modal = (props) => {
    return (
        <div>
            <div className="modal-wrapper"
                style={{
                    transform: props.show ? 'translateY(0vh)' : 'translateY(-100vh)',
                    opacity: props.show ? '1' : '0'
                }}>
                <div className="modal-header">
                    <h3>Modal Header</h3>
                    <span className="close-modal-btn" onClick={props.close}>ร—</span>
                </div>
                <div className="modal-body">
                    <p>
                        {props.children}
                    </p>
                </div>
                <div className="modal-footer">
                    <button className="btn-cancel" onClick={props.close}>CLOSE</button>
                    <button className="btn-continue">CONTINUE</button>
                </div>
            </div>
        </div>
    )
}

export default modal;


Enter fullscreen mode Exit fullscreen mode

The modal component has three props which are:

  • show - a boolean value indicating whether the modal should be shown or not.

  • close - a function which closes the modal when the cancel button is clicked

  • children - which is passed between the opening and closing tags of the modal component as the contents of the modal.

The modal component is a functional component that receives the contents of the modal as the children of the component. The modal footer also contains a button that executes a function to close the modal when it is clicked. The function is passed as a prop to the modal component. The inline style in the modal-wrapper div contains a conditional statement that sets the value of visibility status of the modal depending on the boolean value of the show props.

Modal.css

Add the following code to the Modal.css file in order to add styling to the modal component.

.modal-wrapper {
    background: white;
    border: 1px solid #d0cccc;
    box-shadow: 0 5px 8px 0 rgba(0,0,0,0.2), 0 7px 20px 0 rgba(0,0,0,0.17);
    margin: 100px auto 0;
    transition: all .8s;
    width: 60%;
}

.modal-header {
    background: #263238;
    height: 40px;
    line-height: 40px;
    padding: 5px 20px;
    text-align: right;
}

.modal-header h3 {
    color: white;
    float: left;
    margin: 0;
    padding: 0;
}

.modal-body {
    padding: 10px 15px;
    text-align: center;
}

.modal-footer {
    background: #263238;
    height: 35px;
    padding: 15px;
}

.close-modal-btn {
    color: white;
    cursor: pointer;
    float: right;
    font-size: 30px;
    margin: 0;
}

.close-modal-btn:hover {
    color: black;
}

.btn-cancel, .btn-continue {
    background: coral;
    border: none;
    color: white;
    cursor: pointer;
    font-weight: bold;
    outline: none;
    padding: 10px;
}

.btn-cancel {
    background-color: #b71c1c;
    float: left;
}

.btn-continue {
    background-color: #1b5e20;
    float: right;
}

.back-drop {
    background-color: rgba(48, 49, 48, 0.42);
    height: 100%;
    position: fixed;
    transition: all 1.3s;
    width: 100%;
}

.open-modal-btn {
    margin: 15px;
    padding: 10px;
    font-weight: bold;
}


Enter fullscreen mode Exit fullscreen mode
App.js
import React, { Component } from 'react';

import Modal from './components/Modal/Modal';

class App extends Component {

    constructor() {
        super();

        this.state = {
            isShowing: false
        }
    }

    openModalHandler = () => {
        this.setState({
            isShowing: true
        });
    }

    closeModalHandler = () => {
        this.setState({
            isShowing: false
        });
    }

    render () {
        return (
            <div>
                { this.state.isShowing ? <div onClick={this.closeModalHandler} className="back-drop"></div> : null }

                <button className="open-modal-btn" onClick={this.openModalHandler}>Open Modal</button>

                <Modal
                    className="modal"
                    show={this.state.isShowing}
                    close={this.closeModalHandler}>
                        Maybe aircrafts fly very high because they don't want to be seen in plane sight?
                </Modal>
            </div>
        );
    }
}

export default App;


Enter fullscreen mode Exit fullscreen mode

The App.js file contains two custom functions which are:

  • openModalHandler() - a function that sets the state of isShowing to true thereby opening the modal.

  • closeModalHandler() - a function that sets the state of isShowing to false thereby closing the modal.

In the render method, a backdrop div is dynamically added based on the visibility of the modal and also an onClick listener is passed to the div so it can control the opening and closing of the modal. A button is also added with onClick listener to control the opening of the modal.

The modal component which was previously is imported and used in the render method with the values of the props passed to it.

Testing the modal

Run npm start in the root directory of your project to view the modal.

Project Repo

Thanks.

Discussion (10)

Collapse
bthntprlk profile image
batu

Hi, nice article.

We prefer to use Modal components wrapped in a component which use ReactDOM.portal (comes with 16v) for better UI mechanism. Modals and popups are looks familiar but functionality. For example; you have a form in popup, and you have to show a modal if itโ€™s successfully posted or failed badly. Modals needs to be above popup. Weโ€™ve created 2 roots like app-root; popup-root and modal-root in a large-scaled application. By this way render methods stay clean and UI flows properly without trading CSS hacks, thanks to DOM order.

Thank you for this article (:

Collapse
achowba profile image
Atauba Prince Author

Thanks for the comment, this is the first time I am hearing about ReactDOM.portal, I will go and check it out ๐Ÿ™‚.

Collapse
bthntprlk profile image
batu

(Y) basically it allows you to use components outside of your app-root.

See you (:

Collapse
velocity profile image
Bart Pelle • Edited

Nice write-up! But perhaps not the best to put the children in a <p>? Good article. :)

Collapse
achowba profile image
Atauba Prince Author

Noted...thanks ๐Ÿ™‚

Collapse
ditoorkodashvili profile image
Dito

Hi,
why use two functions (openModalHandler and closeModalHandler) when you can simply have:

toggleModal = () => {
this.setState(prevState=> {
isShowing: !prevState.isShowing
})
}

and also in this kind of situations wouldn't it be more optimal to use functional component with react hooks instead of class?

Collapse
achowba profile image
Atauba Prince Author

Thanks for the suggestion on using the conditional operator. Also, at the time this post was published, React Hooks didn't exist.

Collapse
kazimagha profile image
KazimAgha

Hi, if i want to add Function on Continue button how can i do that?
basically i want to display a dropdown menu as i click continue button

Collapse
achowba profile image
Atauba Prince Author

Hello
Add this below the closeModalHandler

continueFunction = () => {
    // your function body goes here
}
Enter fullscreen mode Exit fullscreen mode

and then change the continue button to this

<button className="btn-continue" onClick={props.close}>CONTINUE</button>
Enter fullscreen mode Exit fullscreen mode
Collapse
ishukanavs profile image
ishukanavs

My Page is very big and there is various open modal button in the center ,bottom and top . but the modal is open in top only... i want it scrollable as per where my button is.... like if i scroll down then this modal also go with it,... how can i do it??? @Atauba Prince