I'm using react dom route v6.
So, I did a structure like this:
<Route element={<AuthenticationRoute/>}>
<Route path="/login/" element={<LoginPage />} />
<Route path="/login/:theme" element={<LoginPage />} />
<Route>
LoginPage has a form, but before, the app needs to check if the user has some storages, if it was already redirected and then it should render the LoginPage.
We needed to do a lot of redirects and all the condition was stored in the LoginPage and it was causing some troubles while it was trying to load the page. So I needed to change and move the conditions/functions.
Now, the component AuthenticationRoute
is a wrapper to redirect if some conditions meet like: doesParameterHasState
? getStorageContainUserId
?
And at a some point, I need to redirect to another website and it returns back to the same path (login/...)
with a hash like this: #state=redirect_uri=value¶m=value.
This hash contains all the query string and I need them to render the LoginPage
.
There's a function here to change #state=redirect_uri=value¶m=value to ?redirect_uri=value¶m=value
But I need to redirect to login/{theme}/ with search: redirect_uri=value¶m=value
I tried to do
export const AuthenticationRoute: FunctionComponent = () => {
const state = changeStateHashToQueryString() // it returns the searchParam (string) or false
const auth = getAuthParam()
if(auth){
return redirectToAnotherPage()
}
if (state){
return (
<Navigate
to={{
pathname: `/login/${getTheme()}`,
search: state
}}
/>)
}
return loading ? <Loading /> : <Outlet>
}
// it's working, #state=query_string=489829384 to ?query_string=489829384
export const changeStateHashToQueryString = () => { return window.location.hash ? `?${window.location.hash.substring(7)}` : false }
// its working
export const getAuthParam = () => {
const params = (new URL(window.location)).searchParams;
return params.get('auth')
}
export const redirectToAnotherPage = () => {
// it calls another function that builds the url and redirect to another webpage (another app), it works normally
}
But it gives me a max depth error.
I know I should return LoginPage, but I need the query string to be working.
If I do pathName "/" it renders correctly, but I need the /:theme/ path to apply the theme.
1 - Should I do window.location.assign
or something?
2 - If I need to redirect with frequency like (userHasStorage, userDidAcceptTheTerms, etc), am I doing correctly? Should I make another page or route?
TLDR:
https://url.com/login/purpleTheme/#state=queryparam=1234&redirect_uri=1234
AuthenticationRoute
should condicionally redirect to login (outlet) with queryparam like this:
https://url.com/login/purpleTheme/?queryparam=1234&redirect_uri=1234
It seems the main issue is that the AuthenticationRoute
component is unconditionally navigating from a "/login/*"
route to a "/login/*"
route which reruns the if (state)
block and rerenders the Navigate
component.
You'll want to gather the information you need and conditionally issue an imperative redirect to the "/login/*"
path with the appropriate queryString params added.
export const AuthenticationRoute: FunctionComponent = () => {
const navigate = useNavigate();
const { pathname } = useLocation();
// Run effect when the route pathname changes
useEffect(() => {
const search = changeStateHashToQueryString();
if (search) {
navigate({
pathname: `/login/${getTheme()}`,
search
});
}
}, [navigate, pathname]);
return loading ? <Loading /> : <Outlet />;
}