DEV Community

Shivam Ranjan Pandey
Shivam Ranjan Pandey

Posted on • Edited on

Creating a reusable Modal component inside React with Portals

During making of any web application Modals are the best way to display information or any feature to user without navigating user to different page.

We will be using reactstrap for displaying a modal.

Our main requirements are :

  1. Making it generic enough to be used whereever we want to display a Modal.
  2. Opening a Modal from a nested child component / maybe even from another modal itself

The second requirement can be handled using the Portals in react.

Why Portals?

In our case we want to display our modal in the top of our DOM tree,but in the cases of nested modal the actual component might be linked to different DOM node, this can create problems and for this main reason we have Portals .

What are Portals?

In React, portals can be used to render an element outside of its parent component’s DOM node while preserving its position in the React hierarchy, allowing it to maintain the properties and behaviors it inherited from the React tree.
A typical use case for portals is when a parent component has an overflow: hidden or z-index style, but you need the child to visually “break out” of its container.
So Portals are the best way to implement Modals for us.

Enough of theory lets get to implementation.

To implement the modal with Portals lets go in "index.html" file and add a dom root where we can render the portal. we are using id="modal-root" where we will render our Portal.

Code


  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <div id="modal-root"></div>


  </body>

Enter fullscreen mode Exit fullscreen mode

Now that we added the render root for the portal lets create a Modal component using Portal.

As we are using reactstrap for displaying the modal, so the Modal tag takes two parameters ,a state variable "isOpen" of boolean type which tells the modal if it has to display or not, and a toggle function which is a function use for changing the state of the Modal.

Code

import React from "react";
import { Modal, ModalBody } from "reactstrap";
import ReactDOM from "react-dom";

const CreateCustomModal = (props) => {
  if (props.isShowing) {
    return ReactDOM.createPortal(
      <>
        <Modal
          isOpen={props.isShowing}
          toggle={() => {
            props.setIsShowing(!props.isShowing);
          }}
        >
          <ModalBody>{props.children}</ModalBody>
        </Modal>
      </>,
      document.querySelector("#modal-root")
    );
  } else return null;
};

export default CreateCustomModal;
Enter fullscreen mode Exit fullscreen mode

as you can see in above code we created a portal and we are rendering it on different dom element i.e,"modal-root".

For the final part we have to make a state variable which
will handle the opening and closing of the modal. The point to be noted here is each component which wants to display the modal will contain their own state variable which handles the opening and closing of the modal, this way we will be able to handle the problem of opening another modal inside an open modal.

Now to solve the first problem to display anything we want in a modal

import the CreateCustomModal component in the component which wants to display modal.Create state variable "isshowing" and pass the variable and its callback to the CreateCustomModal component , enclose the content we want to display in modal between the opening and closing bracket of the CreateCustomModal.

Code

import CreateCustomModal from "./CreateCustomModal";
import React, { useState } from "react";

const DisplayModal =()=> {
  const [isShowing, setIsShowing] = useState(false);
  return (
    <div >
      <h1>I am outside the Modal</h1>
      <CreateCustomModal isShowing={isShowing} setIsShowing={setIsShowing}>
        I am inside a Modal
      </CreateCustomModal>
    </div>
  );
}

export default DisplayModal;

Enter fullscreen mode Exit fullscreen mode

Conclusion

We made a custom Modal component using React Portals and reactstrap

Top comments (1)

Collapse
 
alexsvt2 profile image
Alexis López

Thanks for this example!