Suspense は、配下の UI がまだ表示できない間に fallback を表示する境界です。読み込み中の画面をどこで切り替えるかを、コンポーネントの構造に沿って表現できます。
lazy と組み合わせる
コード分割したコンポーネントを lazy で読み込むとき、Suspense が読み込み中の表示を受け持ちます。
import { lazy, Suspense } from 'react';
const Chart = lazy(() => import('./Chart'));
function Dashboard() {
return (
<Suspense fallback={<p>グラフを読み込み中です…</p>}>
<Chart />
</Suspense>
);
}
Chart の読み込みが終わるまで fallback が表示され、準備できると Chart に切り替わります。
Suspense がすること・しないこと
Suspense は、それ自体でデータ取得を始める仕組みではありません。また、useEffect の中で始めたデータ取得の待機を自動的に検出するものでもありません。
Suspense 対応のデータソースや lazy と組み合わせて、待機中の UI を表現します。読み込み境界を小さくしすぎると画面が細かく切り替わり、大きすぎると必要な部分まで待たせます。利用者にとって自然な単位で境界を置くことが大切です。
fallback を設計する
fallback は単なるスピナーではなく、読み込み中でも画面の構造を伝える UI です。カードや表なら、完成形に近い骨組みを見せるスケルトンも選択肢になります。待機中に何が起きているかをわかりやすく示しましょう。
境界はユーザーの体験単位で置く
ページ全体を一つの Suspense で囲むと、少し遅い部品のために画面全体が fallback へ切り替わることがあります。一方で境界を細かくしすぎると、あちこちで別々のローディング表示が動き、画面のまとまりが失われます。
function ProfilePage() {
return (
<>
<ProfileHeader />
<Suspense fallback={<ActivitySkeleton />}>
<ActivityFeed />
</Suspense>
</>
);
}
この例では、すぐ表示できるプロフィールは残し、準備できていないアクティビティだけを待機表示にします。デザイナーやプロダクトの要求と合わせて、「どこまでが一つの完成した体験か」を基準に境界を決めます。
Error Boundary とは役割が異なる
Suspense が扱うのは、準備できるまでの待機状態です。読み込みの失敗やレンダー中の例外を表示するためには Error Boundary が必要です。待機と失敗を同じ fallback に押し込めず、それぞれの状態に合った UI を設計します。
読み込み中: Skeleton や「読み込み中」
読み込み失敗: 再試行ボタンと説明
空の結果: 次にできる操作の案内
state が保たれるとは限らない
初めて表示しようとした子コンポーネントが suspend した場合、そのレンダーで作られた state は保存されず、再試行時に初期状態からやり直されることがあります。読み込み中にも維持したい入力や選択があるなら、境界の外側や共通の親へ state を置く必要があるか検討します。
Suspense を使う判断
lazy によるコード分割は、Suspense を使う分かりやすい入口です。データ取得については、React と統合されたフレームワークや Suspense 対応のライブラリが提供する方式に従います。Effect で始めた通信を Suspense へ後から接続するものではありません。
まずは、待機表示が必要な UI のまとまりを特定し、その読み込み方法が Suspense をサポートしているかを確認しましょう。