App Routerで特定の意味を持つ予約済みファイル名。これらのファイルを配置することで自動的に特定の機能が有効になる。
// ── layout.tsx: 子ページをラップする共有UI ──────────────
// layout は再レンダーされない(ナビゲーションしても維持される)
export default function RootLayout({
children, // ← 子ページがここに入る
}: {
children: React.ReactNode;
}) {
return (
<html lang="ja">
<body>
<header>ナビゲーション(全ページ共通)</header>
<main>{children}</main> {/* 各ページのコンテンツ */}
<footer>フッター(全ページ共通)</footer>
</body>
</html>
);
}
// ── loading.tsx: データ取得中に自動表示されるUI ──────────
// page.tsx が async でデータ取得している間、これが表示される
export default function Loading() {
return (
<div className="loading-spinner">
<p>読み込み中...</p>
</div>
);
}
// ── error.tsx: エラー発生時に自動表示されるUI ─────────────
// 'use client' が必要(エラー回復のためにクライアント側で動く)
'use client';
export default function Error({
error, // 発生したエラーオブジェクト
reset, // 再試行する関数
}: {
error: Error;
reset: () => void;
}) {
return (
<div>
<h2>エラーが発生しました: {error.message}</h2>
<button onClick={reset}>再試行</button>
</div>
);
}layout.tsxは再レンダーされないため状態を保持できる。page.tsxはURLに対応する実際のコンテンツ。loading.tsxはStreaming SSRと連携して部分的な読み込み表示に使われる。