4

I'm trying to add implement lazy loading in react app which works well in top-level routes. But I also want the <Suspense></Suspense> and provide a fallback for nested routes. According to react-router-dom, there must be only Fragment or Route as the children of Routes. Is there any way to handle this?

Here is the code:

import { lazy, Fragment, Suspense } from "react";
import { BrowserRouter, Route, Routes, Navigate } from "react-router-dom";

import Header from "./components/Header";

const Home = lazy(() => import("./components/layout/Home"));
const Destination = lazy(() => import("./components/layout/Destination"));
const Planet = lazy(() => import("./components/Planet"));
const Crew = lazy(() => import("./components/layout/Crew"));
const Biography = lazy(() => import("./components/Biography"));
const Technology = lazy(() => import("./components/layout/Technology"));
const Procedure = lazy(() => import("./components/Procedure"));

function App() {
  return (
    <BrowserRouter>
      <Header />
      <Suspense fallback={<p className='fixed left-1/2 top-1/2 -translate-x-1/2 text-2xl'>Loading ...</p>}>
        <Routes>
          <Route path="/" element={<Navigate to="home" />} />
          <Route path="home" element={<Home />} />
          <Route path="destination" element={<Destination />}>
            <Route path=":id/:planet" element={<Planet />} />
          </Route>
          <Route path="crew" element={<Crew />}>
            <Route path=":id" element={<Biography />} />
          </Route>
          <Route path="technology" element={<Technology />}>
            <Route path=":id" element={<Procedure />} />
          </Route>
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

export default App;

2 Answers 2

5

You can wrap individual routed components in their own Suspense.

Example:

<BrowserRouter>
  <Header />
  <Suspense
    fallback={(
      <p className='fixed left-1/2 top-1/2 -translate-x-1/2 text-2xl'>
        Loading ...
      </p>
    )}
  >
    <Routes>
      ...
      <Route path="destination" element={<Destination />}>
        <Route
          path=":id/:planet"
          element={(
            <Suspense fallback={<>Loading Planet ...</>}>
              <Planet />
            </Suspense>
          )}
        />
      </Route>
      ...
    </Routes>
  </Suspense>
</BrowserRouter>
Sign up to request clarification or add additional context in comments.

Comments

1

You can also use @loadable/component. here's an instruction about how you can use it.

First, add @loadable/component package to your project.

Then you can change your code to something like this.

import { Fragment, Suspense } from "react";
import { BrowserRouter, Route, Routes, Navigate } from "react-router-dom";
import loadable from '@loadable/component';

import Header from "./components/Header";

const Home = loadable(() => import("./components/layout/Home"));
const Destination = loadable(() => import("./components/layout/Destination"));
const Planet = loadable(() => import("./components/Planet"));
const Crew = loadable(() => import("./components/layout/Crew"));
const Biography = loadable(() => import("./components/Biography"));
const Technology = loadable(() => import("./components/layout/Technology"));
const Procedure = loadable(() => import("./components/Procedure"));

function App() {
  return (
    <BrowserRouter>
      <Header />
      <Suspense fallback={<p className='fixed left-1/2 top-1/2 -translate-x-1/2 text-2xl'>Loading ...</p>}>
        <Routes>
          <Route path="/" element={<Navigate to="home" />} />
          <Route path="home" element={<Home />} />
          <Route path="destination" element={<Destination />}>
            <Route path=":id/:planet" element={<Planet />} />
          </Route>
          <Route path="crew" element={<Crew />}>
            <Route path=":id" element={<Biography />} />
          </Route>
          <Route path="technology" element={<Technology />}>
            <Route path=":id" element={<Procedure />} />
          </Route>
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

export default App;

1 Comment

If I use @loadable/component I don't need Suspense anymore?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.