How to manage external windows (e.g. OAuth popup) with React hooks

Elvis Ciotti
2 min readJun 1, 2021

--

In this article I’ll explain how to to launch a popup on an external URL (e.g. OAuth login), detect when that popup redirects to a different location (OAuth callback) and access the popup URL param values (e.g. code=xyz ) in order to send it to the backend API.

tl:dr;

React doesn’t natively allow to create and control popups, but both creation and checking of the popup can be done with native javascript window.open, by keep the reference in a status variable, and a recurring timer (launched on component mount) to check the status of that popup via the previously saved status variable.

Details and code

Using React 17 with hooks.

Popup creation

First thing is declaring the state variable holding the popup reference

import React, {useEffect, useState} from "react";
const [externalPopup, setExternalPopup] = useState(null);

The clickable element supposed to open the popup will call the following function. I’m keeping it simple by adding all the variables inside to make the example more understandable. This code opens a centred window 500x400 px and stores the window proxy object into the state variable previously declared.

const connectClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
const width = 500;
const height = 400;
const left = window.screenX + (window.outerWidth — width) / 2;
const top = window.screenY + (window.outerHeight — height) / 2.5;
const title = `WINDOW TITLE`;
const url = `HTTPS://AUTH_URL_REPLACE_ME`;
const popup = window.open(url, title, `width=${width},height=${height},left=${left},top=${top}`);
setExternalPopup(popup);
}
<Button ... onClick={connectClick}>Connect</Button>

Access the popup when it changes

You can access the popup anytime via the state variable, but the problem here is that React won’t know when that popup change URL. You can do that by checking every half a second the status of the popup, by launching a setTimeout when the component mounts. I’m using hooks so I’ll place this code in a useEffect, but it should work as well by placing this into componentDidMount.

useEffect(() => {
if (!externalPopup) {
return;
}

const timer = setInterval(() => {
if (!externalPopup) {
timer && clearInterval(timer);
return;
}
const currentUrl = externalPopup.location.href;
if (!currentUrl) {
return;
}
const searchParams = new URL(currentUrl).searchParams;
const code = searchParams.get('code');
if (code) {
externalPopup.close();
console.log(`The popup URL has URL code param = ${code}`);
YourApi.endpoint(code).then(() => {
// change UI to show after the code was stored
})

.catch(() => {
// API error
})
.finally(() => {
// clear timer at the end
setExternalPopup(null);
timer && clearInterval(timer);
})
}
}, 500)
},
[externalPopup]
)

This code basically checks every half a second if the popup contains a codeparameter in the URL. When so, it sends it to the API, and then clears the timeout.

Thanks for reading !

What to do next:
- Clap if useful
- Buy me a coffee
- Follow me for more
- Read my other articles below or from my profile
- Keep in touch on LinkedIn

--

--

Elvis Ciotti

Software Contractor — Java, Spring, k8s, AWS, Javascript @ London - hire me at https://elvisciotti.github.io/