DEV Community

Cover image for 🔧 Build a complete Modal Component with React Hooks 🌈

🔧 Build a complete Modal Component with React Hooks 🌈

viclafouch profile image Victor de la Fouchardière Updated on ・4 min read

Hi guys !

Last week, we talked about 5 Customs React Hooks ! Many of you have shared this article. So this week, let's continue with React and the implementation of a Modal component without installing any packages!

React Modal demo

A Modal component from scratch

Before starting, here are the elements we will use during this tutorial:

  • React Hooks
  • Portals from ReactDOM
  • A little bit of CSS

Let's start with our modal.jsx (or modal.js) file !

Our component:

Let's start with the basics: the creation of our function component. The goal is to include any content to the modal and to manage the opening and closing of the component.

React Modal Hooks

Secondly, what we want is a modal that is independent of our application. We don't want to have any z-index concerns in css or any overflow concerns. So let's insert this component into a different location in the DOM. But how?

Let's introduce the Portals from ReactDOM !

Portals provide a way to render children in a DOM node that exists outside of the DOM component hierarchy, that is, outside of the #root or #app div of your React application.

First, let's add a new div to our html and give it a 'modal-app' ID. React does not create a new div, but displays the children in that modal-app div.

Note that the #modal-app can be any valid element of the DOM (div, section, span...), regardless of its position.

React Modal HTML

And for our component to be inserted in this #modal-app div, let's use the createPortal() method offered by ReactDOM.

React Modal ReactDOM

Even though a portal can be anywhere in the DOM tree, it behaves like a normal React child in every other way. Features like context work exactly the same regardless of whether the child is a portal, as the portal still exists in the React tree regardless of position in the DOM tree.

Source : Portals - React

So let's include this method for our component like this:

React Modal Portals

Open the Modal

Logically, it will be the parent component that will ask the modal to open. But how could we proceed?

First of all, let's add a local state to our Modal component in order to know if the modal is open or not.

useState allows us to create our state with a boolean value. A defaultOpened prop will tell us if we want to open the modal directly on create. false is the default value.

Open React Modal

  • isOpen true === Modal opened
  • isOpen false === Modal closed

We use the conditionally rendering with the JavaScript conditional operator.

Conditionally rendering

Then, in order for the parent to change this local state, you'll have to call up the "refs".

This is where useRef, useImperativeHandle and forwardRef come in.

To call setIsOpen from the parent component, we need to attach a reference to our Modal.

  • useRef is used to attach a reference to our modal.
  • forwardRef is used to forward the reference to the Modal component.
  • useImperativeHandle is used to expose methods to the parent component.

React Modal Opening

Close the Modal

Then, there are several ways to leave a modal.

  • By clicking outside the content of the modal.
  • By using the small cross (x) of our content.
  • By using the ESCAP key of the keyboard.

First, let's capture the keydown event and check if the user use the ESCAP key of his keyboard.

useEffect allowing us to create a listener on the keydown event ONLY if the modal is open. If the user uses the ESCAP key on his keyboard, then the modal closes.

The result is:

React Modal close

The CSS !

You can find the css code here.


React Modal usage

Voilaaa ! Feel free to add your own modifications !


Discussion (4)

Editor guide
zoedreams profile image
jasurkurbanovinit profile image
Jasur Kurbanov

can I use your code for production and personal purposes ?

viclafouch profile image
luiscode92 profile image
Luis Enrique Sanjuan Melo

HEy how can I send propr to the modal? lets say that I want to zoom a img from the parent to a modal(child) how can I pass the img as a prop?