Learn to create Modal in ReactJs using Portals

Learn to create Modal in ReactJs using Portals

Β·

4 min read

What is a Modal? πŸ€”

Modals are UI elements that sit on top of an application's main window - often with a layer of transparency behind them to give users a peek into the main application. To return to the application you need to interact with the modal.

It is used to direct the user's attention to an important action or piece of information. You can use a modal in lots of cases πŸ› .

In this blog, we will discuss how to create a Modal component in our ReactJs Component, using Portals.

Setting up the project

Create a new react project (using Terminal or PowerShell) and start it up

npx create-react-app modal-example
cd modal-example
npm run start

Creating Modal Component 😎

First, we need to add a new div in public/index.html

<div id="modal"></div>
<div id="root"></div>

Create a new Modal.js file in the src/ folder.

Now, we need to import some items.

import { useEffect, useRef } from 'react'
import { createPortal } from 'react-dom'

Create a Modal functional component and export it by default.

// modal component
const Modal = ({ children }) => {
    ...
}

export default Modal

Now, inside the component first, create a ref using the useRef hook.

 const elementRef = useRef(null)

Create a new div using this ref

if(!elementRef.current){
  elementRef.current = document.createElement("div")
}

Now, we are gonna use the useEffect hook to make our modal functional

 useEffect(() => {
    // it is the div we created in index.html
    const modalRoot = document.getElementById("modal")
    document.body.style.overflow = "hidden"    // disable scrolling functionality when modal is open
    modalRoot.appendChild(elementRef.current)

    // destroy this modal after use
    return () => {
        document.body.style.overflow = "unset"
        modalRoot.removeChild(elementRef.current)
    }

}, [])

We append ref div in the modal id div present in index.html. We also need to disable scrolling behind the overlay when the modal is open.

The return statement is used to destroy the div from DOM and also to enable scrolling after the modal is closed.

At the end of our component, we need to return a Portal. Learn more about portals here.

return return createPortal(<div>{children}</div>, elementRef.current);

The final file looks like this,

// In Modal.js

import './Modal.css'

// importing modules
import { useEffect, useRef } from "react";
import { createPortal } from "react-dom";

// Modal Component
const Modal = ({ children }) => {
    const elementRef = useRef(null);

    // we are create a div using ref
    if (!elementRef.current) {
        elementRef.current = document.createElement("div");
    }

    useEffect(() => {
        // it is the div we created in index.js
        const modalRoot = document.getElementById("modal");
        document.body.style.overflow = 'hidden';    // disabling overflow functioning

        modalRoot.appendChild(elementRef.current);

        // to destroy this modal after use
        return () => {
            document.body.style.overflow = 'unset'  // enabling overflow functioning
            modalRoot.removeChild(elementRef.current)
        };
    }, [])

    return createPortal(<div>{children}</div>, elementRef.current);
}

export default Modal;

Now, we need to add some CSS in our component, create a new Modal.css file and add the below code to it.

#modal {
    background-color: rgba(0, 0, 0, 0.6);
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    top: 0;
    z-index: 10;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  #modal:empty {
    display: none;
  }

Using Modal component 🀯

If you render a component, the parent can capture its events regardless of whether it’s implemented using portals.

Create a new state called show using useState hook. By default, it is set to false.

const [show, setShow] = useState(false)

Now, we are gonna use conditional rendering to add our modal in.

{
    show
    ?
    <Modal>
     ...
    </Modal>
    :
    null
}

Create a button to open modal by setting show state to true on click.

<div>
  <button onClick={ () => setShow(true) }>
    Click Me!
  </button>
</div>

To close the modal, we need to set the state back to false this can be done in a number of ways. See the code below.

// In App.js

import './App.css'

import { useState } from 'react';
import Modal from './Modal';

function PopUp(props) {
  return (
    <div className="popUp">
      <h1>
        This is a modal!
      </h1>

      <button onClick={() => { props.setShow(false) }}>
        Close
      </button>
    </div>
  )
}

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

  return (
    <div className="App">
      {
        show
          ?
          <Modal>
            <PopUp setShow={setShow} />
          </Modal>
          :
          null
      }

      <div>
        <button onClick={() => setShow(true)}>
          Click me!
        </button>
      </div>
    </div>
  );
}

export default App;

Check out the whole code here.

Conclusion

In this blog, we discussed how to use Portals and References to create a Modal component in ReactJs.

We saw how to disable the scrolling functionality of our application.

Additionally, we also talked about how to use the state to open and close the Modal component.

You can explore more about them or learn more, by checking React's official documentation about Refs and Portals.

And if you're having any doubts please mention them in the comments below!πŸ‘¨β€πŸ’»

Β