Next.jsのファイルシステムルーティング
チュートリアルを行っていた時にNext.jsのファイルシステムルーティングがわからなかったのでメモ。
1. URLにしたいページはapp
ディレクトリ配下にpage.tsx
を作成する
-
page.tsx
とはReactコンポーネントをエクスポートする特別なNext.jsファイル -
/app/page.tsx
→ホームページとなる -
app/URLにしたいディレクトリ名/page.tsx
→ディレクトリ名をパスにしたURLとなる- ディレクトリ名を
dashboard
にしてその中にpage.tsx
を作成
- ディレクトリ名を
2. ナビゲーションなどの共通化したい部分はlayout.tsx
を使う
-
layout.tsx
とはナビゲーションなど複数のページで共有されるUIを作成するためのファイル- そのディレクトリ以下のすべてのページに適用される
- 例:
app/dashboard/layout.tsx
→/dashboard
- ページコンポーネントのみが更新され、レイアウトは再レンダリングされないことが特徴
// app/dashboard/layout.tsx
export default function Layout({ children }) {
return (
<div>
<SideNav />
{children}
</div>
);
}
- ルートにある
/app/layout.tsx
(ルートレイアウト)についてはフォントなどアプリケーション内のすべてのページで共有したいことを書く- ルートレイアウトは必須
-
<html>
と<body>
タグを含める必要がある
-
- ルートレイアウトは必須
3. URLに影響を与えたくない場合には ルートグループ(括弧付きディレクトリ)を使う
- 例:
app/(dashboard)/page.tsx
→ URLは/
になる((dashboard)
はURLに含まれない) - コードの整理や共通のレイアウトをグループ化するのに使う
app/
├─ (dashboard)/ ← URLに含まれない
│ ├─ page.tsx ← URL: /
│ └─ layout.tsx ← このレイアウトは (dashboard) 内のページにのみ適用
└─ (auth)/ ← URLに含まれない
├─ login/
│ └─ page.tsx ← URL: /login
└─ register/
└─ page.tsx ← URL: /register
4. 同じURLで複数のページを表示させたい場合にはパラレルルート(@folder
)を使う
- パラレルルートは同じURLで複数のページを同時に表示する機能
- パラレルルートはlayout.tsxでのみ使える
- page.tsxではパラレルルートを受け取れない
- layout.tsx で受け取る際、フォルダ名と同じ名前のプロパティで受け取る
export default function Layout({ children, analytics, settings }) {
return (
<div>
{children} {/* メインのページ */}
{analytics} {/* @analytics の内容 */}
{settings} {/* @settings の内容 */}
</div>
);
}
- フォルダ名を
@
で始めると、同じ階層のlayout.tsxに渡して両方表示することができる
app/
└─ dashboard/
├─ @analytics/ ← パラレルルート
│ └─ page.tsx ← 分析ページ
├─ @settings/ ← パラレルルート
│ └─ page.tsx ← 設定ページ
├─ layout.tsx ← 両方のページを表示するレイアウト
└─ page.tsx ← メインのページ
5. モーダル表示したい場合にはインターセプト
- インターセプトルートは同じURLでモーダルを表示する機能
- 同じURLでモーダルを表示したい場合、
(..)
をディレクトリ名につける「インターセプト(横取り)」が使える- メリット
- URLが変わらない:モーダルを開いてもURLが変わらない
- 戻るボタンで閉じられる:ブラウザの戻るボタンでモーダルを閉じられる
- メリット
- モーダルを開いた状態のURLをシェアするにはクエリパラメータを使う
- 例:
/tasks?id=task-123
- 例:
app/
└─ tasks/
├─ page.tsx ← タスク一覧
└─ @modal/
├─ modal.tsx ← モーダル自体
└─ (..)tasks/
└─ page.tsx ← タスク詳細/編集
6. ローディングUI(loading.tsx
)
- ページの読み込み中に表示するUIとして
loading.tsx
を作成することもできる- 例:
app/dashboard/loading.tsx
→ ダッシュボードの読み込み中に表示
- 例:
- ローディングUIは自動的に表示される
- ページの読み込み中に自動的に表示され、読み込みが完了すると自動的に非表示になる
7. エラーハンドリング(error.tsx
)
- エラー発生時に表示するUI
- 例:
app/dashboard/error.tsx
→ ダッシュボードでエラーが発生したときに表示 - エラーハンドリングはクライアントコンポーネントとして実装する必要がある
-
'use client'
ディレクティブを追加する
-
8. Not Found
(not-found.tsx
)
- ページが見つからないときに表示するUI
- 例:
app/dashboard/not-found.tsx
→ ダッシュボードのページが見つからないときに表示
- 例:
- データが見つからない場合、ユーザーが見つからない場合など
notFound()
関数を呼び出すとNot Found
ページを表示できる
まとめ
ファイルシステムルーティングを使う場合にはこれらを使って作成していく
- URLにしたいページ →
app/URLにしたいディレクトリ名/page.tsx
- 共通のレイアウト → Playout.tsx`
- URLに影響を与えたくない場合 → ルートグループ(括弧付きディレクトリ)
- 同じURLで複数のページを表示 → パラレルルート(
@folder
) - モーダル表示 → インターセプトルート(
(..)
)
app/
├─ (dashboard)/ ← URLに含まれない
│ ├─ page.tsx ← URL: /
│ └─ layout.tsx ← このレイアウトは (dashboard) 内のページにのみ適用
├─ tasks/
│ ├─ page.tsx ← タスク一覧
│ └─ @modal/
│ ├─ modal.tsx ← モーダル自体
│ └─ (..)tasks/
│ └─ page.tsx ← タスク詳細/編集
└─ layout.tsx ← ルートレイアウト
その他:サーバーサイド側のロジックってどこにおくんだろう?
1. appディレクトリ内に配置
- Next.jsの公式ドキュメントで使っているのは
app/lib
配下におく方法👀
app/
├─ lib/ ← ロジックを配置
│ ├─ actions.ts ← サーバーアクション
│ └─ utils.ts ← ユーティリティ関数
├─ components/ ← コンポーネント
└─ dashboard/
└─ page.tsx
2. appディレクトリと並列に配置
プロジェクトルート/
├─ app/ ← ページとレイアウト
├─ lib/ ← ロジックを配置
└─ components/ ← コンポーネント
3. 'use client'と'use server'
を使って同一ファイル内で定義することも可能
-
'use client'
→ ファイルの先頭に書く -
'use server'
→ 関数の先頭に書く
'use client'; // ファイル全体がクライアントコンポーネントになる
export default function Page() {
// クライアントコンポーネント
const [count, setCount] = useState(0);
// サーバーアクション
async function handleClick() {
'use server'; // この関数のみサーバーサイドで実行
await db.update('users', { count: count + 1 });
}
return <button onClick={handleClick}>クリック</button>;
}