TL;DR
App Router の app ディレクトリに置く特別なファイルの 1 つ。page.tsx を包む Suspense コンポーネントのフォールバックとして表示される。
仕組み
Suspense コンポーネントは自動で挿入される。layout.tsx はその外側(親の階層)に位置する。
<Layout>
<ErrorBoundary fallback={<Error />}>
<Suspense>
<Page />
</Suspense>
</ErrorBoundary>
</Layout>通常は Server Component だが、Client Component にもできる。props は受け取れない。
公式ドキュメントによると、loading.tsx はナビゲーションのときにすぐ表示される読み込み中の UI を作るためのもので、ルートセグメントの中身がストリーミングで届くと自動で差し替わる。同じ階層の layout.tsx、template.tsx、error.tsx は Suspense で包まない。フォールバックの UI はプリフェッチされるので、プリフェッチが終わっていればナビゲーションはすぐに切り替わる。ナビゲーションは中断でき、読み込みが終わるのを待たずに別のルートへ移れる。共通のレイアウトは新しいセグメントの読み込み中も操作できる。
例
export default function Loading() {
return <>...Loading</>
}注意点
公式ドキュメントによると、レイアウトが cookies() や headers()、キャッシュしない fetch などの実行時のデータを使うと、loading.tsx のフォールバックは表示されない。ナビゲーションをすぐに切り替えるには、そのデータの取得を page.tsx に移すか、レイアウトの中で別の <Suspense> で包む。
ストリーミングのレスポンスは 200 のステータスコードで始まる。ストリーミングが始まったあとに notFound などを呼んでも、ステータスコードは変わらない。
自分の理解
拡張子は .jsx(.js)でもよい。