DEV Community

Michael Burrows
Michael Burrows

Posted on • Originally published at w3collective.com

Building a React modal component using a custom Hook

In this tutorial we’ll be building a custom React modal component that can be used to display a variety of web elements including: forms, alert messages, or images.

Let’s get started by using Create React App to setup our application:

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

In the /src folder create a new file called useModal.js which will contain the useModal() custom Hook. Custom Hooks should always start with use so that you can quickly tell that it’s a re-usable Hook:

import { useState } from 'react';

const useModal = () => {
  const [visible, setVisible] = useState(false);
  function toggle() {
    setVisible(!visible);    
  }
  return {toggle, visible}
};

export default useModal;
Enter fullscreen mode Exit fullscreen mode

Also in the /src folder create a new file called Modal.js for the modal component itself:

import React from "react";
import ReactDOM from "react-dom";

const Modal = ({ visible, toggle }) => visible ? ReactDOM.createPortal(
  <div className="modal">
    <div className="modal-pop" role="dialog" aria-modal="true">
      <h3>Hello World</h3>
      <p>Et sit saepe velit tenetur et consequatur in. Nihil doloribus nulla nulla rem. Soluta illo et asperiores numquam earum nesciunt. Vero odio voluptatem sunt sunt laboriosam.</p>
      <button type="button" onClick={toggle}>Close</button>
    </div>  
    <div className="modal-overlay"></div>    
  </div>, document.body
) : null;

export default Modal;
Enter fullscreen mode Exit fullscreen mode

If visible is true we use a Portal to render the modal into a DOM node that exists outside the DOM hierarchy of the parent component, in this instance the <body>. This is because modals need to be the last DOM element in a page to meet accessibility requirements.

We can now pull it all together by modifying the App.js file as follows:

import Modal from './Modal';
import useModal from './useModal';
import './App.css';

const App = () => {
  const {toggle, visible} = useModal();
  return (
    <div className="App">
      <button onClick={toggle}>Show Modal</button>
      <Modal visible={visible} toggle={toggle} />
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Finally add some basic CSS to App.css so we can test the functionality:

.modal-pop {
  background: #fff;
  border: 2px solid #aaa;
  border-radius: 5px;  
  z-index: 999;
  max-width: 420px;
  margin: auto;
  padding: 1em 2em 2em;
  position: relative;
}
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 99;
  background-color: #000;
  opacity: 0.75;
}
Enter fullscreen mode Exit fullscreen mode

You can now test the modal by running the npm start command.

Whilst this example is quite simple it demonstrates how to build a functioning modal component that you can customise for use in future projects. Thanks for reading and be sure to check out my other tutorials on building React components.

Top comments (1)

Collapse
 
harshilparmar profile image
Harshil Parmar

This is because modals need to be the last DOM element in a page to meet accessibility requirements.

Can you please explain this in more detail?