首页 > 解决方案 > How to use multiple react suspense fallbacks with reach router?

问题描述

I'm using "@reach/router": "^1.2.1" and in my App.js file I've got a fallback component to show while my routes are loading:

<React.Suspense fallback={<MainLandingPageLoadingScreen />}>
  <Router>
    <MainLandingPage path="/" />
    <AnotherLandingPage path="/coolbeans" />
    <NotFound default />
  </Router>
</React.Suspense>

But depending on the route, I want to use a different loading component as the fallback, so something like:

<Router>
  <React.Suspense fallback={<AnotherLandingPageLoadingScreen />}>
    <MainLandingPage path="/" />
    <NotFound default />
  </React.Suspense>

  <React.Suspense fallback={<AnotherLandingPageLoadingScreen />}>
    <AnotherLandingPage path="/coolbeans" />
  </React.Suspense>
</Router>

This won't work because Router needs to be wrapped around Suspense, instead of this way around. But if I split it like below then the second Router list doesn't get picked up and the route is a 404:

<React.Suspense fallback={<MainLandingPageLoadingScreen />}>
  <Router>
    <MainLandingPage path="/" />
    <NotFound default />
  </Router>
</React.Suspense>

<React.Suspense fallback={<AnotherLandingPageLoadingScreen />}>
  <Router>
    <AnotherLandingPage path="/coolbeans" />
  </Router>
</React.Suspense>

What is the correct way to provide a fallback component on a routing level?

标签: reactjsreact-loadablereach-routerreact-suspense

解决方案


嘿,所以我在这个场景中使用了 React Router 而不是 Reach Router,但我认为同样的想法也适用。

您仍然希望在所有路由周围只包含 1 个 Suspense 组件:

<Router>
  <React.Suspense fallback={// will get to this}>
    <MainLandingPage path="/" />
    <NotFound default />
    <AnotherLandingPage path="/coolbeans" />
  </React.Suspense>
</Router>

但是您需要创建一个函数来传递给检查特定组件的路径名的回退。React 路由器有 useLocation() 钩子,它可以为你获取路径名,看起来 Reach 路由器也有定位功能。

您的函数将尝试匹配路径名,并根据您导航到的路径返回适当的加载组件:

const showAppropriateLoadingComponent = (pathname: string) => {
  switch (pathname) {
    case '/':
      return <LoadingComponent1 />;
      break;
    case '/coolbeans':
      return <LoadingComponent2 />;
      break;
    case default:
      return <DefaultLoadingComponent />
      break;
  }
}

然后在您的实际路由器文件中,您只需调用 suspense fallback 中的函数并将路径名作为参数传递。

const Router = () => {
  const { pathname } = useLocation();
  <Router>
    <React.Suspense fallback={showAppropriateLoadingComponent(pathname)}>
      <MainLandingPage path="/" />
      <NotFound default />
      <AnotherLandingPage path="/coolbeans" />
    </React.Suspense>
  </Router>
}


推荐阅读