9

These are the two components i am having, My question is where do i place the <React.Suspense> component to load the routes as required?

Navagtion/index.jsx

import React from "react";
import {
  RouterProvider,
  createBrowserRouter,
  createRoutesFromElements
} from "react-router-dom";
import Root from "./Root";

const router = createBrowserRouter(createRoutesFromElements(Root));

const Navigation = () => {
  return <RouterProvider router={router} />;
};

export default Navigation;

Root.jsx

import React from "react";
import { Route } from "react-router-dom";

const PublicLayout = React.lazy(() => "../Layouts/PublicLayout");
const PrivateLayout = React.lazy(() => "../Layouts/PrivateLayout");

const Index = React.lazy(() => "../Pages");
const Welcome = React.lazy(() => "../Pages/Welcome");
const Login = React.lazy(() => "../Pages/Login");
const Register = React.lazy(() => "../Pages/Register");

const Root = (
  <Route path="/" element={<Index />}>
    <Route element={<PublicLayout />}>
      <Route path="/login" element={<Login />} />
      <Route path="/register" element={<Register />} />
    </Route>

    <Route element={<PrivateLayout />}>
      <Route path="/welcome" element={<Welcome />} />
    </Route>
  </Route>
);

export default Root;

How can i Lazy Load routes inside component? Where do i wrap All routes from Suspense.

Amandeep Kochhar
  • 91
  • 1
  • 1
  • 3

2 Answers2

4

The remix-run/react-router demo shows wrapping each lazily imported component in their own React.Suspense component:

import React from "react";
import { Route } from "react-router-dom";

const PublicLayout = React.lazy(() => "../Layouts/PublicLayout");
const PrivateLayout = React.lazy(() => "../Layouts/PrivateLayout");

const Index = React.lazy(() => "../Pages");
const Welcome = React.lazy(() => "../Pages/Welcome");
const Login = React.lazy(() => "../Pages/Login");
const Register = React.lazy(() => "../Pages/Register");

const Root = (
  <Route
    path="/"
    element={(
      <React.Suspense fallback={<>...</>}>
        <Index />
      </React.Suspense>
    )}
  >
    <Route
      element={(
        <React.Suspense fallback={<>...</>}>
          <PublicLayout />
        </React.Suspense>
      )}
    >
      <Route
        path="/login"
        element={(
          <React.Suspense fallback={<>...</>}>
            <Login />
          </React.Suspense>
        )}
      />
      <Route
        path="/register"
        element={(
          <React.Suspense fallback={<>...</>}>
            <Register />
          </React.Suspense>
        )}
      />
    </Route>

    <Route
      element={(
        <React.Suspense fallback={<>...</>}>
          <PrivateLayout />
        </React.Suspense>
      )}
    >
      <Route
        path="/welcome"
        element={(
          <React.Suspense fallback={<>...</>}>
            <Welcome />
          </React.Suspense>
        )}
      />
    </Route>
  </Route>
);

export default Root;

React.lazy

You can place the Suspense component anywhere above the lazy component. You can even wrap multiple lazy components with a single Suspense component.

You could also create a layout route that wraps a React.Suspense around an Outlet component.

Example:

import React from "react";
import { Route } from "react-router-dom";

const PublicLayout = React.lazy(() => "../Layouts/PublicLayout");
const PrivateLayout = React.lazy(() => "../Layouts/PrivateLayout");

const Index = React.lazy(() => "../Pages");
const Welcome = React.lazy(() => "../Pages/Welcome");
const Login = React.lazy(() => "../Pages/Login");
const Register = React.lazy(() => "../Pages/Register");

const SuspenseLayout = () => (
  <React.Suspense fallback={<>...</>}>
    <Outlet />
  </React.Suspense>
);

const Root = (
  <Route element={<SuspenseLayout />}>
    <Route path="/" element={<Index />}>
      <Route element={<PublicLayout />}>
        <Route path="/login" element={<Login />} />
        <Route path="/register" element={<Register />} />
      </Route>
      <Route element={<PrivateLayout />}>
        <Route path="/welcome" element={<Welcome />} />
      </Route>
    </Route>
  </Route>
);

export default Root;

Since the React.Suspense component just needs to be higher in the tree than the lazy component, you might also wrap the RouterProvider in Navigation in the Suspense component.

import React from "react";
import {
  RouterProvider,
  createBrowserRouter,
  createRoutesFromElements
} from "react-router-dom";
import Root from "./Root";

const router = createBrowserRouter(createRoutesFromElements(Root));

const Navigation = () => {
  return (
    <React.Suspense fallback={<>...</>}>
      <RouterProvider router={router} />
    </React.Suspense>
  );
};

export default Navigation;
maz
  • 642
  • 8
  • 14
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
2

I placed it wrapping the Root component on the route element, and it works like this:

/router/index.jsx

const Root = lazy(() => import('../layout/Root'))

const Home = lazy(() => import('../pages/Home'))
const About = lazy(() => import('../pages/About'))
const Experience = lazy(() => import('../pages/Experience'))
const Projects = lazy(() => import('../pages/Projects'))
const Contact = lazy(() => import('../pages/Contact'))

export const router = createHashRouter([
  {
    path: '/',
    element: <Suspense fallback={<Loader />}><Root /></Suspense>,
    errorElement: <NotFound />,
    children: [
      {
        index: true,
        element: <Home />
      },
      {
        path: '/about',
        element: <About />
      },
      {
        path: '/experience',
        element: <Experience />
      },
      {
        path: '/projects',
        element: <Projects />
      },
      {
        path: '/contact',
        element: <Contact />
      }
    ]
  }
])