React 惰性/暂停 + React Router 在获取组件之前不会更改路由

cmp*_*rog 5 reactjs react-router code-splitting react-router-dom

我正在开发一个应用程序,它使用默认的 React 代码分割,使用 Lazy/Suspense 方法和 React Router 进行组件渲染。目前,当我导航到另一个路径时,如果网速较慢,在获取组件时会更新路径并渲染回退组件,是否有办法在当前路径上等待组件包完全下载?

Pat*_*rts 3

是的,在启用的并发模式下,您可以创建一个自定义路由器,以将历史对象上的useTransition()每个导航方法包装在悬念转换中:

import { useState, unstable_useTransition as useTransition } from 'react';
import { Router } from 'react-router-dom';

const SuspenseRouter = ({ children, history, ...config }) => {
  const [startTransition, isPending] = useTransition(config);
  const [suspenseHistory] = useState(() => {
    const { push, replace, go } = history;

    history.push = (...args) => {
      startTransition(() => { push.apply(history, args); });
    };
    history.replace = (...args) => {
      startTransition(() => { replace.apply(history, args); });
    };
    history.go = (...args) => {
      startTransition(() => { go.apply(history, args); });
    };
  });

  suspenseHistory.isPending = isPending;

  return (
    <Router history={suspenseHistory}>
      {children}
    </Router>
  );
};

export default SuspenseRouter;
Run Code Online (Sandbox Code Playgroud)

示例用法可能如下所示:

import { Suspense, lazy, unstable_createRoot as createRoot } from 'react';
import { Switch, Route } from 'react-router-dom';
import { createBrowserHistory } from 'history';
import SuspenseRouter from './components/SuspenseRouter';

const history = createBrowserHistory();

const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));

const App = () => (
  <SuspenseRouter history={history} timeoutMs={2000}>
    <Suspense fallback="Loading...">
      <Switch>
        <Route path="/" exact={true} component={Home} />
        <Route path="/about" component={About} />
      </Switch>
    </Suspense>
  </SuspenseRouter>
);

createRoot(document.getElementById('root')).render(<App />);
Run Code Online (Sandbox Code Playgroud)

如果您想在上一条路线上无限期等待,请设置timeoutMs为。Infinity在上面的示例中,将其设置为2000应在上一个路由上等待最多 2 秒,fallback如果此时尚未下载所请求路由的代码,则显示 。

  • 这是一个更新版本,适用于 React 18 和 React-router 6,并且还可以在刷新后处理浏览器后退按钮。https://gist.github.com/perlow/bb7612b25f37667be964f1a1aba42780 (3认同)