Managing pop-ups using react-router

IT’s Bruise
7 min readMay 2, 2020

I’m going to show you two ways of how to manage pop-ups using react-router. I want it to be not just a theoretical talk so I decided to prepare a demo and GitHub sources.

Let’s take the simplified semblance of Instagram as a test project

Here we see three posts. When you click on any of the posts, they all lead to a separate page

There are additional buttons on that page (“LIKES”, “VIEWERS”) by clicking on which you can find out who saw this post and who liked it.

I want you to pay your attention to the following:

First, when we opened the popup, the URL was changed in the browser bar and “/likes” was added to the end of the URL. Try to open and close the popup in the demo and you’ll see how the URL address changes. This is necessary for keeping pop-up open after refreshing the page. Therefore, you can share a link to those who liked this post even on social media. For example, Twitter has a similar system, so when you click, for example, on a picture, it will be opened in a pop-up in a separate route. And if you refresh the page, the pop-up will be still opened.

Secondly, if you open and close the popup several times and then click the back arrow in the browser, then you won’t go through all these pop-up’s closings and openings again, you want just get back

Thirdly, this one is a very important point. When you click to close the popup, the URL address changes instantly, but the animation of closing popup itself takes a little bit of time, it takes only 300ms in our case, this is a frequent requirement of designers.

Ok, now we’re going to take a deeper look at how this works.

Let’s open component PostCard and look into the code

As you can see, we explicitly pass the children as a property to the Route component instead of component/render, or simply put it inside the route as we usually used to do. The difference is that this property absolutely always mounts in the DOM what is passed to children, it doesn’t matter if the URL address matches path or not

On the one hand, the property “match” will be null if the path does not match and on the other hand will be the object if the path matches the current URL. So we can use this field to manage the opening and closing of the popup and due to the fact that the dialog never unmounts, the popup can easily complete the animation of closing the dialog box

In order to prevent traces of opening a modal window in history, we call history.goBack() on the popup closing event, which removes the last record from the history stack. In this case, it behaves like pop-up was never opened in a browser, but we have one problem case if you open the popup by direct link and try to close pop-up then you will return to the previous website. It’s absolutely unacceptable behavior and how to solve it you can find at the next video:

Okay, I think I have already introduced you to this approach in detail. Let’s move on to the second way of working with dialogs

Next to the posts, there is a sign in button, by clicking on it a pop-up with a form opens. In this variant, the URL also changed, but instead of changing the pathname, we got a GET parameter. This was implemented so that the pop-up is not connected to any specific page, so it can be opened from anywhere. For example, we’ll go inside any post, there you can open a pop-up login in the same way

Also, in such kind of pop-ups, you can pass data using additional GET parameters. For example, if you open the notification pop-up and select notification there, you will see that another GET notification-id parameter has been added

If you refresh the page using this parameter, you will see that the state of the pop-up will be restored in the same way. Moreover, if you select different notifications, and then press the back arrow in the browser, all GET parameters will disappear. In other cases, this popup behaves as in the previous approach

This technique is actively used by many sites such as Google, also in YouTube analytics. And here’s one more example in the Gmail mail service, if there are attachments in the email and if you click on them then a preview will be opened in the popup. Please note that the same GET parameters appear and again you can restore the state of the page using these parameters

Let’s finally see how it works!

The first thing I start with is creating the config file. There I set GET parameters which are used in the project and use them instead of string constants

If one of the GET parameters can be set as an ENUM, I create one more config file. It will help to keep track of the values and use them all over the project

Next, I create my custom hook useGetParameter that gets the value from the GET parameter. URLSearchParams is a browser API to work with GET parameters. The react-router-dom library uses this API in their examples

The next step is to bind the name to the component itself. This is a kind of alternative to the classic switch case approach

Based on this, we can easily create a GetParameterPopups component. Using our useGetParameter hook we can get the name of the current pop-up and substitute the appropriate component. This code works great except the fact that it doesn’t support closing animations, because as soon as the URL changes, the manager will return null instead of pop-up

So let’s create one more custom hook useGetPopupState where we can set a new state variable mountedPopup

And we will change mountedPopup value to null with a delay of 300ms — this is the animation time for closing the popup. And in case of switching from one popup to another, change the value without delay

The last thing that we need to do is to calculate isOpened, as we need to inform the popup that it’s time for him to be closed before we replace it with null. Then we return these values to the component. And it will look like this:

Now mountedPopup controls which popup to display and we pass parameter isOpened to the component to control popup open and close without delay

The SignIn popup itself looks familiar to you, it gets isOpened from the parent, and when closing it calls history.goBack()

The Notifications pop-up seems to be more interesting, it works with additional GET parameters, and there is no additional garbage in the browser history. How does it work? I will leave it for you to figure it out

I think you have learned the approach (more details), use it to make your website better. Better even than Google does. If you liked the topic, please write comments and I will share more tricks!

--

--

IT’s Bruise

Owner of an innovative IT channel on YouTube: EN — “IT’s Bruise” and RU — ”АйТи Синяк”