3

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?

Simpleton
  • 6,285
  • 11
  • 53
  • 87

1 Answers1

1

Hey so I had this scenario using React Router instead of Reach Router, but I think the same idea will apply.

You still want to just have 1 Suspense component wrapped around all of your routes:

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

But you will need to create a function to pass into the fallback that checks for the pathname of the specific component. React router has the useLocation() hook which grabs the pathname for you, it looks like Reach Router has a location function as well.

Your function will just try to match the pathname, and return the appropriate loading component based on what path you navigate to:

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

Then in your actual router file, you just call the function in the suspense fallback and pass in the pathname as the param.

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