11.1 Suspense
Suspenseは、子ツリーの準備が整うまでフォールバックを表示する境界である。
<Suspense fallback={<Spinner />}>
<Comments />
</Suspense>
Suspense対応対象:
lazyで読み込むコード- Suspense対応フレームワークのデータ
useで読み取るPromise- Server Componentsストリーム
任意のfetchをuseEffectで呼ぶだけではSuspense対応にならない。
11.2 lazy
const SettingsPage = lazy(() => import("./SettingsPage"));
function App() {
return (
<Suspense fallback={<p>読み込み中...</p>}>
<SettingsPage />
</Suspense>
);
}
11.3 use
function Message({ messagePromise }: {
messagePromise: Promise<string>;
}) {
const message = use(messagePromise);
return <p>{message}</p>;
}
Promiseが未解決なら、最寄りのSuspense境界へ処理を移す。
レンダリング中に毎回新しいPromiseを作ると安定しない。Server Component、フレームワークキャッシュ、親から渡されたPromiseなどを使う。
11.4 useTransition
緊急性の低い更新をTransitionとして扱う。
const [isPending, startTransition] = useTransition();
function selectTab(nextTab: string) {
startTransition(() => {
setTab(nextTab);
});
}
入力値そのものの更新など即時反映が必要な処理をTransitionにしない。
11.5 useDeferredValue
const deferredQuery = useDeferredValue(query);
const results = useMemo(
() => searchLargeList(deferredQuery),
[deferredQuery]
);
入力は即時更新し、重い結果表示は遅延させる。
11.6 Suspense境界設計
- ローディング体験のまとまりで配置する
- 小さく分けすぎてちらつかせない
- 画面全体を単一境界に閉じ込めない
- Error Boundaryと組み合わせる
- SSRストリーミングの単位として考える