1

I implemented lazy loading routes with lazy and suspense in order to reduce the main bundle size.

However, I run into the issue that, when refreshing the page, the app always end up in the wildcard route instead of reloading at the current location url.

If I remove the wildcard, the issue seems to be fixed, but then I miss the behavior of being redirected on wrong url input. If I remove the lazy/suspense combo and load the routes on the main bundle, the issue also is fixed, but then I obviously lose the benefits of lazy loading.

Why is that ? What could be done to allow the refresh to end up on the previous route ?

// Lazy imports
const Home = lazy(() => import("./home/Home"));
const RecordsModule = lazy(() => import("./records/Records"));

function App() {
  // ...some logic
  // No use of lazy loading here
  return (
    <BrowserRouter>
      <Switch>
        <Route exact path="/">
          <Redirect to={isLoggedIn ? "/main" : "/auth"} />
        </Route>
        <Route path="/auth">
          <Auth />
        </Route>
        <Route path="/main">
          {!isLoggedIn && <Redirect to="/auth" />}
          <Main />
        </Route>
        <Route path="*">
          <Redirect to="/" />
        </Route>
      </Switch>
      <Toaster />
    </BrowserRouter>
  );
}

function Main() {
  // ...some other logic
  /*
    Here the Home and RecordsModule components are lazy loaded.
    If the user refreshes the page while being on /main/records,
    the resulting refresh will bring him on /main/home.
    
    If I put a console.log in the wildcard route,
    it appears to be the route used after the refresh.
    
    The issue is not present if not using lazy loading or removing the wildcard route.
  */
  return (
    <div className="main">
      <Switch>
        <ErrorBoundary>
          <Suspense
            fallback={
              <FullPageContainer>
                <Spinner />
              </FullPageContainer>
            }
          >
            {/* This will redirect to /main/home if coming from /main  */}
            <Route exact path={match.path}>
              <Redirect to={`${match.path}/home`} />
            </Route>
            {/* /main/home */}
            <Route path={`${match.path}/home`}>
              <Home />
            </Route>
            {/* /main/records */}
            <Route path={`${match.path}/records`}>
              <RecordsModule />
            </Route>
            {/* Redirects to /main/home if none of the above is matched */}
            <Route path="*">
              <Redirect to={`${match.path}/home`} />
            </Route>
          </Suspense>
        </ErrorBoundary>
      </Switch>
      <Menu />
    </div>
  );
}
Pierre Burton
  • 1,954
  • 2
  • 13
  • 27
  • Do you think you could create a *running* codesandbox demo that reproduces this issue that we could inspect and debug live? I suspect it may be because you wrap an entire set of routes in the `Suspense` wrapper instead of individual routes. I would like to test this theory against your code. – Drew Reese Apr 05 '22 at 05:15

1 Answers1

1

Solved by migrating to React router v6.

npm i react-router@latest

Migration guide from v5

Pierre Burton
  • 1,954
  • 2
  • 13
  • 27