Master the suspension mechanism, lazy component loading, and bundle splitting.
Open this lesson in KodokonSuspense relies on a little-known mechanism: a component that does not yet have its data or its code suspends its rendering. Under the hood, the current implementation throws a promise, which React intercepts just as it would intercept an error. React then walks up to the nearest <Suspense> boundary, displays its fallback, then replays the render of the subtree once the promise resolves. It is an implementation detail (never throw a promise yourself), but it explains all the observable behavior: the boundary acts as a declarative catch for async work. The historical use case is code splitting with React.lazy.
import { lazy, Suspense } from 'react';
const Chart = lazy(() => import('./Chart'));
function Dashboard() {
return (
<Suspense fallback={<Spinner />}>
<Chart points={data} />
</Suspense>
);
}lazy expects a function that returns a promise resolving to a module with a default export. The splitting itself is the bundler's job: each dynamic import() becomes a split point and produces a separate chunk, loaded on demand. A common subtlety in real codebases: your components are often named exports. You then need to adapt the module on the fly.
const Chart = lazy(() =>
import('./charts').then((module) => ({
default: module.Chart,
}))
);The tricky part in production: during a navigation, content that is already displayed can suspend again (new route, new chunk) and be abruptly replaced by the fallback. Since React 18, an update wrapped in startTransition changes this behavior: React keeps the previous interface on screen while the new render suspends in the background, and only shows the fallback for content that has never been revealed. Boundaries also compose in depth: several nested <Suspense> boundaries let you reveal the interface zone by zone, from the global skeleton down to the details.
const [isPending, startTransition] = useTransition();
function openTab(nextTab) {
startTransition(() => {
setTab(nextTab);
});
}
// The current tab stays visible while the new
// one loads, instead of dropping back to the fallback.React.lazy return?