Search code examples
javascriptreactjstypescriptreact-routerreact-router-dom

Max depth error on Navigate with 2 paths react router v6 and authentication page/wrapper problems


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&param=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&param=value to ?redirect_uri=value&param=value But I need to redirect to login/{theme}/ with search: redirect_uri=value&param=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:

  1. I want to enter the page: https://url.com/login/purpleTheme/#state=queryparam=1234&redirect_uri=1234
  2. Component AuthenticationRoute should condicionally redirect to login (outlet) with queryparam like this: https://url.com/login/purpleTheme/?queryparam=1234&redirect_uri=1234

Solution

  • 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 />;
    }
    

    Edit max-depth-error-on-navigate-with-2-paths-react-router-v6-and-authentication-page