Building a modal with Reactjs portal

Last updated : Jul 30, 2023 12:00 AM

This article explains how to display a modal dialog using Reactjs portals. A fully functional sample react project is available to download at the end of this article.

1. Overview

Modals are reusable message containers that are displayed on top of the screen, blocking background contents. Modals usually put an overlay on the screen to block interaction with the parent screen. Therefore, it is good practice to keep the modal separate from the rest of the application code. React portals allow us to render content into a different part of the dom, enabling us to maintain the modal in a separate dom node.

2. Creating a root element to mount the modal

When you create the react project, the package manager automatically creates a root element to mount the main application. This HTML element is located in the index.html. Now we have to add another element to mount our modal.

<!DOCTYPE html>
<html lang="en">
  <head>
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <div id="modal-root"></div>
  </body>
</html>

3. Creating modal to mount

The next step is to mount the modal in the newly created dom element. The modal code is listed below. Most of the code follows a regular React component pattern, except for how we render the component to the dom. The RenderModal component accepts a ReactNode as props and mounts it in the modal-root dom element.

import { ReactNode } from "react"
import ReactDOM from 'react-dom';

export interface CardProps {
    children: ReactNode
}

export const RenderModal = (props:CardProps) => {
    return ReactDOM.createPortal(props.children, document.getElementById("modal-root")!)
}

4. Modal code

Listed below is a simple modal component to display a popup with an overlay.

import styles from "./local.module.css"

interface ModalProps {
    onClose: (showModal: boolean) => void
}

export const YesNoDialogModal = (props: ModalProps) =>{
  return(
    <div className={styles.modal}>
    <span onClick={() => props.onClose(false)} className={styles.close}>×</span>
      <form className={styles.modalContent}>
        <div className={styles.container}>
          <h1>We use cookies</h1>
          <p>Would you like to proceed?</p>
          <div className={styles.clearfix}>
            <button type="button" onClick={() => props.onClose(false)} className={styles.cancelbtn}>Cancel</button>
            <button type="button" onClick={() => props.onClose(false)} className={styles.deletebtn}>Ok</button>
          </div>
        </div>
      </form>
    </div>
  )
}

5. Controlling the modal in App.tsx

Simple logic to display and close the modal.

import React, { useState } from 'react';
import { RenderModal } from './components/modal/RenderModal';
import { YesNoDialogModal } from './components/modal/YesNoDialogModal';

export const App = () => {
   const [showModal, setShowModal] = useState(false)
   return (
      <>
         <RenderModal>
            {showModal && <YesNoDialogModal onClose={setShowModal}/>}
         </RenderModal>
         <h2>Cookie Modal</h2>
         <button onClick={() => setShowModal(true)}>Open Modal</button>
      </>
   );
}
export default App;

If you inspect the dom using chrome developer tools, you will notice the additional dom element we added to the index.tsx. The open modal button adds the modal HTML to the modal-root dom element. The HTML clears when the modal is closed.

Download Reactjs modal and portal example

Lance

By: Lance

Hi, I'm Lance Raney, a dedicated Fullstack Developer based in Oklahoma with over 15 years of exp

Read more...