Manage Popups Easily In React

Learn how you can better manage modals using React Context

Guy Warzager
Wix Engineering
3 min readJun 2, 2020

--

Portal managed poorly in Evil dead 2

Introduction

If you already are frustrated enough with managing popups in React, you can definitely skip my grumbling and jump to Let’s start, and we shall build a modal manager using context.

If you are working with React for a while, you probably thought to yourself isn’t weird having to manage the state of a modal each time with the same isOpen, isVisible key words.

Especially when it is a prompt dialog such as “Are you sure?”, or a toast message saying “Action has been completed successfully”
What does these modals have to do with the current component?!
Where in the component’s render function am I supposed to add them?!
How do I reuse them in a list? Do I need to hold in the state the clicked item in the list?

React projects get complex enough as is. Having to manage states of modals just makes the code less readable, increases the state size of each component, and duplicates logic throughout the system.
All this repeating code also increases the system’s bundle size.

“These pretzels are making me thirsty!” — Seinfeld

In most cases you want to open a popup with some initial data, and not manipulate it’s props while it’s already open.
And when it closes you want to get its result in a callback.
Doesn’t this feel like an API would be the best approach?

So, Why isn’t there a react-popup-manager solution out there?!
Let’s create one!

(there actually is one. so why waste time on learning it if you can just skip to using it — here it is)

Let’s Start

You probably heard by now about context. You haven’t? So, it provides a way to pass data through the component tree without having to pass props down manually at every level (thanks react docs).

Popups are global in nature, are usually shoved to the top of the DOM to avoid z-index blockage. Often times you’ll want to reuse them everywhere in the system. You probably know where i’m going with this… so..

Lets code

Lets break it down:

PopupManager

A service that will be the only point of handling popups in our entire system.

Kinda straight forward. there is a list of popups.
You open it, and it is set to isOpen:true. You close it, and it is set to isOpen:false.

The pub-sub code will be clear by the next paragraph.

PopupsWrapper

Here it will render all the open popups in the system. it’s in the root of the application.

As you can see here, the component subscribes to the popupManagers pub-sub by calling subscribeToPopupsChange. And calls forceUpdate in order to re-render when there is a change in the popups. Go back a paragraph and you’ll see callPopupsChangeEvents is triggered in open and in close functions. so we can be certain the changes will get to the DOM.
onClose will allow sending params back to caller, but more on that later…

Last step - use the context

Now some react hocus pocus.

This is a wrapper function component, that passes the popupManager as a prop to any component that needs to consume that service without being an immediate child.
Remember that PopupProvider, when we created PopupContext? So here we are using it.
If this syntax seems confusing check again the react docs here

Lets use this, awesome, yet very simple ,mini-library

Boilerplate time

Now the application is wrapped with the PopupProvider.

Here we used withPopups to add popupManager as a prop to the component.

isOpen and onClose were added by the popupWrapper.
The rest were sent using the popupManager’s open function.

and… Done!

Army of Darkness

This was a simple, shorter than 3 mins read, implementation.
Luckily, there is a library that does this and more.

Check it out here:

Example with and without react-popup-manager

The old way — Using state

The new way — Using react-popup-manager

I hope there will eventually be a season 4, and that I managed to convince you to use this approach.

--

--