How do I redirect my user back to an existing tab?
When a user signs in to my app, I open a new tab (using window.open(url, '_blank')
) to contain the signin sequence. After the user completes the signin, I want that tab to close and return to tab that was active before the new tab was opened.
Here is a screenshot of the application when the user is unknown:
When the user clicks the "Signin" button at top right, here is a screenshot showing the second tab (containing the password challenge from Auth0):
At the successful conclusion of the signin, here is the placeholder behavior. The Switch
complains because I don't know what to do in response to the "continuation" URL:
Here is what the application looks like after a successful signin. I get this by manually refreshing the browser after closing the second tab. Note the Avatar at the top right.
How do I programmatically cause the final screen shot? I want to close the second tab, return to the first tab, and force a render.
I'm lost in the weeds of "window.open" and the behaviors of react-router-dom
. My authentication provider is Auth0, and so the application already has a Auth0ProviderWithHistory
context as well as a Router
around that. That Auth0ProviderWithHistory
already has code that's doing something with history
:
const history = useHistory();
const onRedirectCallback = (appState) {
history.push(appState?.returnTo || window.location.pathname);
}
I'm new enough to react-router-dom
that I don't really grok what the useHistory
and useParams
hooks do. At the top of my app, I have a dispatcher that uses Switch
and Route
to determine the contents that appear in whatever tab is open. The flow through the several signin stages that use the dispatcher seems to work fine. Here is the AppDispatcher
that I'm currently using:
import React from 'react';
import {
Box,
} from '@mui/material';
import { Route, Switch } from 'react-router-dom';
import AppContainer from './AppContainer';
import LoginPersonaContainer from './login_persona/LoginPersonaContainer';
import SigninPersonaContainer from './login_persona/SigninPersonaContainer';
import SuccessContainer from './login_persona/SuccessContainer';
import ClosedContainer from './login_persona/ClosedContainer';
const NoMatch = ({ location }) => (
<Box>
<strong>Error!</strong> No route found matching:
{location.pathname}
</Box>
);
const AppDispatcher = () => {
return (
<Switch>
<Route
path="/"
exact = {true}
component={AppContainer}
/>
<Route
path='/loginPersona/login'
component = {LoginPersonaContainer}
/>
<Route
path='/loginPersona/signin'
component = {SigninPersonaContainer}
/>
<Route
path='/loginPersona/success'
component = {SuccessContainer}
/>
<Route
path='/loginPersona/closed'
component = {ClosedContainer}
/>
<Route
component={NoMatch}
/>
</Switch>
);
}
export default AppDispatcher;
I don't see a way to cause the second tab on the browser to close while returning control to the initial tab -- and forcing a render on that tab so that it will reflect the results of the signin.
When the code in the second window just closes the window (window.close
), the tab closes but the original window doesn't render. I've tried a variety of alternatives, and they either open a third tab or render the original window's content in the new tab. Neither of those is acceptable.
What react-browser-dom
or window
incantation causes the "signin" tab to close, return control to the original tab, and force a render/refresh of the original window?
CodePudding user response:
When the second tab loads, You can use
window.opener.document.location.href = "http://localhost:3000"
window.close()
This will go back to the parent tab, and cause it to re-render. Then the second tab will also be closed.
You have to make sure that this code only runs when you visit the route on the second tab
You can find more information about it here https://developer.mozilla.org/en-US/docs/Web/API/Window/opener