Chapter 2 of 4
Lazy Loading Components
Splitting the bundle with lazy and Suspense.
lazy takes a function returning a dynamic import and gives you a component. The chunk is fetched the first time the component renders.
import { lazy, Suspense } from "react";
const SettingsPanel = lazy(() => import("./SettingsPanel"));
function App() {
const [showSettings, setShowSettings] = useState(false);
return (
<>
<button onClick={() => setShowSettings(true)}>Settings</button>
<Suspense fallback={<Spinner />}>
{showSettings && <SettingsPanel />}
</Suspense>
</>
);
}The module must have a default export
// SettingsPanel.jsx
export default function SettingsPanel() { /* ... */ }
// For a named export, map it yourself
const Chart = lazy(() =>
import("./charts").then((module) => ({ default: module.BarChart }))
);Preloading
Waiting until the click to start downloading adds a visible delay. Start the fetch on hover or focus, so the chunk is usually ready by the time it is needed.
const load = () => import("./SettingsPanel");
const SettingsPanel = lazy(load);
<button onMouseEnter={load} onFocus={load} onClick={open}>
Settings
</button>Handling a failed chunk
A network failure while loading a chunk throws, so pair Suspense with an error boundary - covered in the next tutorial.
<ErrorBoundary fallback={<p>Could not load this section.</p>}>
<Suspense fallback={<Spinner />}>
<SettingsPanel />
</Suspense>
</ErrorBoundary>