0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.jsのファイルシステムルーティング

Posted at

Next.jsのファイルシステムルーティング

チュートリアルを行っていた時にNext.jsのファイルシステムルーティングがわからなかったのでメモ。

1. URLにしたいページはappディレクトリ配下にpage.tsxを作成する

  • page.tsxとはReactコンポーネントをエクスポートする特別なNext.jsファイル
  • /app/page.tsx→ホームページとなる
  • app/URLにしたいディレクトリ名/page.tsx→ディレクトリ名をパスにしたURLとなる

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 Foundnot-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>;
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?