Creating a Reusable Modal Dialog in React Bootstrap

Motivation

A modal dialog box is a graphical user interface element that is commonly used in programming to display information or prompt the user for input. It is a type of window that requires the user to interact with it before they can return to other parts of the application. Modal dialog boxes are useful when developers want to interrupt the user's workflow to gather input or display critical information that requires immediate attention. They can be used for a variety of purposes, such as displaying error messages, asking the user to confirm an action, or displaying a form for data entry.

For my fifth project for Code Institute, I built a recipe sharing site using React Bootstrap components. When the user clicked on an icon to delete a recipe, I wanted a popup dialog to appear asking them to confirm their choices. In this article, I show you how to implement a reuseable modal dialog component in React to ask for confirmation before executing a delete function.

  • I assume you have React application running and the Boostrap react library installed.
  • The focus of this article is on the implementation of a reusable component, not style. The component we create will have the default styling.
  • We are not worried about folder structure.

Creating the Modal Component

The first thing we want to do is create a file called ModalAlert.jsx and store it in an appropriate folder in your project - ie wherever you store files for your components and add the following. (I have exaggerated spacing for readability.)

// (1) The imports
import React from 'react';
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';

//(2) props
function ModalAlert({show,  handleClose, onConfirm, title, message, buttonLabel}) { 
  return (

    //(3) Declare Modal component.
    <Modal show={show} onHide={handleClose} onClose={handleClose}> 

    //(4) Define the Header
    <Modal.Header>
      <Modal.Title>{title}</Modal.Title>
    </Modal.Header>


    //(5) The body of our modal.
    <Modal.Body>
      {message}
    </Modal.Body>


    // (6) Footer with buttons
    <Modal.Footer>
      <Button onClick={handleClose}>
        Close
      </Button>
      <Button onClick={onConfirm}>
        {buttonLabel}
      </Button>
    </Modal.Footer>


  </Modal>
  )
}

export default ModalAlert

Let us look at this one section at a time. (1) is just the import statements. Nothing there.

In part (2) we have function ModalAlert({show, handleClose, onConfirm, title, message}). All we are doing is declaring a functional component called ModalAlert and passing it some props. Let's example what those props are. Remember, that these props come from the parent.

  • show This is a boolean If true, the dialog will show. If false, it will be hidden.
  • handleClose is a callback method that will execute when the user clicks on the Close button.
  • onConfirm is a callback method that will execute when the user clicks on the Delete button. In other words, by clicking on the Delete button the user confirms that they want the item deleted.
  • title is a string that will be used for the title of the modal.
  • message is string that will me used to display text to the user in the body of the modal.
  • buttonLabel is a string to name the button. It can be whatever you want the "confirm" button to say. For example, "Save", "Delete", "Confirm" etc

OK. Props explained let's get to the rest.

In part (3) we have<Modal show={show} onHide={handleClose} onClose={handleClose}> where we pass down our props to the show, onHide, and onClose properties of the Modal component. show, onHide, and onClose are properties from the React Bootstrap library. Notice that we use the same callback for onHide and onClose.

In part (4) we add a <Modal.Header> component with a <Modal.Title> component as a child. In the <Modal.Title>, we render the title prop. <Modal.Title>{title}</Modal.Title>.

In part (5) we add a <Modal.Body> component which renders the message prop.

In part (6), we add a <Modal.Footer> component with two <Button> components as children. Placing the buttons in the footer will lay them out properly - to the right side of the dialog box.

For each button we pass a callback to its onClick property. We pass our onConfirm prop to the onClick property for the Delete button and the handleClose callback to the onClick property of the Close button.

That's it for setting up our component. Now let's use it. This component will get what it needs from the parent.

Using the Modal Component

The first thing to do is to place your modal component into the component tree of wherever you want that modal to be displayed. For example, you might have a component tree like the following excerpt. Remember this is an excerpt and an example. I have left out the rest of the file for clarity and readability.

//Import Statements

//Methods and variables
<>
<Book>
    <Title />
    <Author />
    <Description />
    <DeleteIcon />
</Book>

<ModalAlert 
show={}
handleClose={}
onConfirm={}
title={}
message={}
buttonLabel{}
/> //Get that component into the tree!
</>

OK. we placed our modal component into the tree. Now let us pass it the props it needs.

Start easy. Lets give it the title, message, and buttonLabel data it needs. These are just strings.

<ModalAlert 
show={}
handleClose={}
onConfirm={}
title={"Confirm Delete"}
message={"Delete the Book?"}
buttonLabel={"Delete"}
/>

Now let's set the onConfirm property. This will be a callback. So we must write a function containing the code to execeute when the user confirms the action and pass its name to the property. (Remember in this case it will be clicking on the Delete button.)

const handleDelete = () => {

    //Code to delete the book.
    //Remember the delete function is just an example. You can program the buttons to do whatever you want.
};


<>
<Book>
    <Title />
    <Author />
    <Description />
    <DeleteIcon />
</Book>

<ModalAlert 
show={}
handleClose={}
onConfirm={handleDelete}
title={"Confirm Delete"}
message={"Delete the Book?"}
buttonLabel={"Delete"}
/> //Get that component into the tree!
</>

Now for the hard part. We need a variable which will be a boolean to keep track of whether or not the ModalAlert is to be visible or not. Using a state hook is a good way to do this. We create a state variable called show along with a setShow method and set its initial value to false (since we don't want the dialog to initially be visible.) We can then pass this variable to the show property of our dialog. const [show, setShow] = useState(false);

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

    //Code to delete the book.
    //Remember the delete function is just an example. You can program the buttons to do whatever you want.
};


<>
<Book>
    <Title />
    <Author />
    <Description />
    <DeleteIcon />
</Book>

<ModalAlert 
show={show}
handleClose={}
onConfirm={handleDelete}
title={"Confirm Delete"}
message={"Delete the Book?"}
buttonLabel={"Delete"}
/> //Get that component into the tree!
</>

We can pass the callback for handleClose now. No need for a separate method. We can do this inline.

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

    //Code to delete the book.
    //Remember the delete function is just an example. You can program the buttons to do whatever you want.
};


<>
<Book>
    <Title />
    <Author />
    <Description />
    <DeleteIcon />
</Book>

<ModalAlert 
show={show}
handleClose={() => setShow(false)} // Just set show to false. The dialog will disappear.
onConfirm={handleDelete}
title={"Confirm Delete"}
message={"Delete the Book?"}
buttonLabel={"Delete"}
/> //Get that component into the tree!
</>

We are almost done. But the problem remains, how and do we get your dialog to appear? To make it appear, we call the setShow method like this setShow(true). Which will set show to true and this make the dialog appear. However, when that should be called is up to you. In this case, I would like the dialog to appear when the user clicks on the <DeleteIcon> component. I would therefore pass the following callback to its onClick method: <DeleteIcon onClick={()=>setShow(true)}/>. Our final code would look like this:

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

    //Code to delete the book.
    //Remember the delete function is just an example. You can program the buttons to do whatever you want.
};


<>
<Book>
    <Title />
    <Author />
    <Description />
    <DeleteIcon onClick={()=>setShow(true)}/>
</Book>

<ModalAlert 
show={show}
handleClose={() => setShow(false)} // Just set show to false. The dialog will disappear.
onConfirm={handleDelete}
title={"Confirm Delete"}
message={"Delete the Book?"}
buttonLabel={"Delete"}
/> //Get that component into the tree!
</>

That is it! To make sure you understand, go through the article one more time to make sure you see how things are connected and when the functions will run. Add a comment if anything is confusing or if you want clarification.

BootstrapReactComponentsModals
Avatar for tony-albanese

Written by tony-albanese

Loading

Fetching comments

Hey! 👋

Got something to say?

or to leave a comment.