带有惰性和 Suspense 的 React 路由器总是在页面刷新时退回到通配符路由
React router with lazy and Suspense always falls back on wildcard route on page refresh
为了减少主包的大小,我用 lazy 和 suspense 实现了延迟加载路由。
但是,我 运行 遇到了一个问题,即在刷新页面时,应用程序总是以通配符路径结束,而不是在当前位置重新加载 url。
如果我删除通配符,问题似乎就解决了,但后来我错过了在错误 url 输入时被重定向的行为。
如果我删除 lazy/suspense 组合并在主包上加载路由,问题也得到解决,但显然我失去了延迟加载的好处。
这是为什么?可以做些什么来让刷新在以前的路线上结束?
// 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>
);
}
通过迁移到 React 路由器 v6 解决
npm i react-router@latest
为了减少主包的大小,我用 lazy 和 suspense 实现了延迟加载路由。
但是,我 运行 遇到了一个问题,即在刷新页面时,应用程序总是以通配符路径结束,而不是在当前位置重新加载 url。
如果我删除通配符,问题似乎就解决了,但后来我错过了在错误 url 输入时被重定向的行为。 如果我删除 lazy/suspense 组合并在主包上加载路由,问题也得到解决,但显然我失去了延迟加载的好处。
这是为什么?可以做些什么来让刷新在以前的路线上结束?
// 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>
);
}
通过迁移到 React 路由器 v6 解决
npm i react-router@latest