javascript 32 lines · 6 steps

Lazy-loaded routes in React

Split each page into its own bundle and load it on demand, with a spinner and an error net around the swap.

Explained by highlit
1import { lazy, Suspense } from "react";
2import { Routes, Route, NavLink } from "react-router-dom";
3import ErrorBoundary from "./components/ErrorBoundary";
4import Spinner from "./components/Spinner";
5 
6const Dashboard = lazy(() => import("./pages/Dashboard"));
7const Reports = lazy(() => import("./pages/Reports"));
8const Settings = lazy(() => import("./pages/Settings"));
9 
10export default function AppRoutes() {
11 return (
12 <div className="app-shell">
13 <nav className="sidebar">
14 <NavLink to="/" end>Dashboard</NavLink>
15 <NavLink to="/reports">Reports</NavLink>
16 <NavLink to="/settings">Settings</NavLink>
17 </nav>
18 
19 <main className="content">
20 <ErrorBoundary fallback={<p>Failed to load this section.</p>}>
21 <Suspense fallback={<Spinner label="Loading" />}>
22 <Routes>
23 <Route path="/" element={<Dashboard />} />
24 <Route path="/reports" element={<Reports />} />
25 <Route path="/settings" element={<Settings />} />
26 </Routes>
27 </Suspense>
28 </ErrorBoundary>
29 </main>
30 </div>
31 );
32}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Wrapping dynamic imports in lazy() lets each route ship as a separate chunk fetched only when visited.
  2. 2Suspense supplies a loading fallback for any lazy child while its bundle downloads.
  3. 3An ErrorBoundary outside Suspense catches chunk-load failures so a bad network doesn't blank the whole app.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Lazy-loaded routes in React — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code