Search justacoding.blog. [Enter] to search. Click anywhere to close.

April 29th, 2022

Create Your Own React Modal Component

Modals are very much a staple of the web.

They are a handy way to use the screen’s available real estate to display content on-top-of content.

Creating your own modal component in React is straightforward enough. This makes it a suitable task for React beginners to sink their teeth into, and it’s a good way to learn about some important React fundamentals and best practices in the process.

Here’s a React Modal component example for you to take a look at.

In this tutorial, we’ll talk through the various aspects of this component in particular.

So let’s get started!

Overview of the React Modal component

As you can see, the modal is fairly lightweight. In fact, it’s constructed entirely from one singular component.

Let’s break down what the component actually does and how it works:

  • You can wrap content within the Modal component itself
  • Some element on your page (typically a link or a button) will be responsible for opening this modal
  • The content is now nested within the modal, which overlays the rest of the page’s content
  • The modal can be closed with a x button or something similar

That’s the most basic implementation of the modal.

We’ll step through each of these aspects in turn, next.

Building the actual modal itself

It’s important to consider that the modal is essentially a single “dumb” component (as opposed to a “smart” component – be sure to read about the differences if you aren’t familiar).

It can perform actions — like doing something on clicking “okay” or “cancel” buttons, but those are actions passed down to it from above. It isn’t directly responsible for the underlying logic or functionality of these particular actions.

Similarly, the modal doesn’t have any of it’s own internal state, it just renders out a view based on the provided props. This is what we mean by “dumb” component.

The various props – passing content to the modal component

You’ll notice the first prop passed in is called children. This is a special prop – as this can be used to pass whatever you wrap with your component. Like so:

<Modal>
  <h1>I'm a child!</h1>
</Modal>

In this trivial example, the full h1 element will be exposed under the children props within the Modal component. This is pretty neat, as it allows for some more verbose composition, as shown.

You could of course elect to pass your modal’s content directly as a regular prop instead, but this was feels a lot more suitable in some cases.

Add the ability to override aspects of the modal

You’ll also notice two props called headerOverride and footerOverride.

If supplied, these props allow the developer to override the content that should populate the header and footer elements of the modal respectively.

Here’s the header override:

<div className="header">
  {headerOverride ? (
    <Fragment>{header}</Fragment>
  ) : (
    <div className="titleBar">
      <div className="title">{title}</div>
      <div className="close" onClick={onClose}>X</div>
    </div>
  )}
</div>

And here’s the footer override:

<div className="footer">
  {footerOverride ? (
    <Fragment>{footer}</Fragment>
  ) : (
    <div className="controls">
      {onCancel && <button onClick={onCancel}>{cancelText}</button>}
      {onOkay && <button onClick={onOkay}>{okayText}</button>}
    </div>
  )}
</div>

By default, “cancel” and “okay” buttons are provided out of the box (ie. in the footer). This simply makes it easier to keep a consistent style and structure throughout all of the various uses of the modal within the app.

However, there are times when you’ll want to circumvent this standard. So you may want an extra button alongside the cancel button, or you may want nothing at all to display for example.

In this case, you can make use of the various override props provided, and instead pass your own complete element(s) instead of relying on the default configuration.

Passing functionalities to the modal

Next, we’ll look at onClose, onCancel and onOkay.

These props simply represent functions that the modal itself can make use of.

You’ll notice each of those functions is attached to various elements of the user interface within the modal.

onClose is attached to the background overlay as well as the x button.

<div className="overlay" onClick={onClose}></div>

onCancel is attached to the “cancel” button, and conversely, onOkay is attached to the “okay” button.

{onCancel && <button onClick={onCancel}>{cancelText}</button>}
{onOkay && <button onClick={onOkay}>{okayText}</button>}

Closing the modal should be self-explanatory. We just need to provide a mechanism to toggle the boolean that governs the modal’s visibility. This is controlled outside of the component, more on this later.

Clicking “cancel” or “okay” would do whatever is required by the use-case. So for instance pressing “okay” could submit some data to the backend via a network request, and clicking “cancel” could firstly show an alert or confirm box — before invoking the relevant onClose function, also.

Opening and closing the modal

We’re feeding an isOpen prop to our React modal component, this is the single source of truth that dictates whether the modal should be open or closed. So we’re essentially just showing and hiding the full component each time.

const [modalIsOpen, setModalIsOpen] = useState(false)

<Modal
  isOpen={modalIsOpen}
  // ...

The modal doesn’t care about any logic that governs this isOpen boolean – it simply just receives the boolean and either opens or closes itself accordingly.

Likewise, the onClose function we previously mentioned comes from outside of the component. The modal just invokes this function upon a specific interaction (clicking the x button for instance).

Remember that the modal component is a dumb component – there is some kind of state outside of the modal that is controlling it’s visibility, in this case, that would be the modalIsOpen state.

Improving the modal

This particular React modal component example is fairly straightforward. However, there are a few improvements that can be made to further enhance the functionality.

Let’s take a look at some of those improvements.

Modal navigation or pagination

This isn’t necessarily a common requirement, but it would be interesting to interject some form of navigation within the modal.

This would make it possible to scroll or navigate to a different screen within the modal by clicking on various different arrow keys or other navigational elements, for instance.

For this, you’d likely want the concept of “screens”. Opening the modal would present screen 1 (by default), with the facility to move back and forward through the other various screens or pages.

As stated, it’s perhaps not a typical requirement — but it could definitely be useful in some scenarios, all the same.

Full screen mode

There are a lot of styling or structural changes you can apply to this modal.

One example would be a full screen mode.

By default, the modal is a “regular” size, and it’s docked within the screen, neatly within the center.

It may be nice to pass a prop (for example isFullScreen) that would alter the styling and structure to cover the full width and height of the screen. This would be especially useful for when the modal needs to display lots of content, as it could save the user from having to scroll too much.

In closing

I hope you’ve found this article and the accompanying React modal component example somewhat useful!

If you’re looking for more articles of this kind, please do feel free to checkout out the code examples category.

There are various other articles that work in the same manner – a simple component accompanied by an article providing a fairly detailed overview of the main aspects of the design.

Thanks for reading!

Have any questions? Ping me over at @justacodingblog
← Back to blog