テック教育ナビ アイコン

テック教育ナビ

Next.jsの動的ルート(Dynamic Routes)の使い方


Next.js最終更新日: 2024-12-12
Next.jsの動的ルート(Dynamic Routes)の使い方

Next.jsでは、Dynamic Routes(動的ルート)を使用して、事前にURLセグメント名を決定せず、リクエスト時やビルド時に動的にルートを生成できます。この仕組みは、ブログ記事や商品ページのように動的なデータを扱う際に便利です。

【この記事で学べること】

  • Dynamic Routesの基本と作成方法
  • 動的セグメントでparamsを活用する方法
  • 静的パラメータ生成(generateStaticParams)の仕組み
  • Catch-allセグメントとOptional Catch-allセグメントの使い方

1. Dynamic Routesの基本

Dynamic Segmentの作成

Dynamic Segmentは、フォルダ名を角括弧[]で囲むことで作成します。

例: ブログ記事のルート

plaintext
app/
  blog/
    [slug]/
      page.tsx

上記の構造では、[slug]が動的セグメントとなり、/blog/:slug形式のURLを扱えます。

コード例: 動的セグメントを使用

tsx
// app/blog/[slug]/page.tsx
export default function Page({
  params,
}: {
  params: { slug: string }
}) {
  const slug = params.slug;
  return <div>My Post: {slug}</div>;
}

動作例

RouteURLparams
/blog/[slug]/page.tsx/blog/a{ slug: 'a' }
/blog/[slug]/page.tsx/blog/b{ slug: 'b' }

2. 静的パラメータ生成(generateStaticParams

generateStaticParams関数は、Next.jsのビルド時に動的なルートを静的に生成するための仕組みです。ブログ記事や製品詳細ページのように、コンテンツがデータベースやAPIで管理されている場合に便利です。

例: ブログ記事ページ: 例えば、ブログ記事をAPIから取得して、それぞれの記事に対応する静的なページを生成したい場合を考えます。

tsx
// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
  const posts = await fetch('https://api.example.com/posts').then((res) =>
    res.json()
  );

  return posts.map((post) => ({
    slug: post.slug,
  }));
}
  • 具体的な動作

    • APIから記事リストを取得: API(例: https://api.example.com/posts)にリクエストを送り、すべてのブログ記事のslugを取得します。

    • ルートの生成: slugに基づき、以下の静的ルートがビルド時に生成されます。

      • /blog/post-1
      • /blog/post-2
  • 利点

    • データ取得が自動的にメモ化され、ビルド時間が短縮されます。
    • ビルド時に確定したルートを作成し、高速なパフォーマンスを実現。

3. Catch-allセグメント

Dynamic Routesは、...を使って「Catch-allセグメント」を定義できます。これにより、複数のパスセグメントを1つの動的ルートでキャプチャできます。たとえば、カテゴリーやサブカテゴリーを持つECサイトで利用します。

ユースケース: ECサイトのカテゴリーページ

以下のフォルダ構造を持つサイトでは、/shop/a/shop/a/bのような任意の深さのカテゴリーURLに対応できます。

plaintext
app/
  shop/
    [...slug]/
      page.tsx
 

コード例

tsx
// app/shop/[...slug]/page.tsx
export default function CategoryPage({ params }: { params: { slug: string[] } }) {
  return (
    <div>
      <h1>カテゴリ: {params.slug.join(' > ')}</h1>
    </div>
  );
}

動作例

RouteURLparams
/shop/[...slug]/page.tsx/shop/a{ slug: ['a'] }
/shop/[...slug]/page.tsx/shop/a/b{ slug: ['a', 'b'] }

4. Optional Catch-allセグメント

Optional Catch-allセグメント([[...slug]])は、URLのセグメントが存在しても、しなくても対応可能な柔軟なルート設定を提供します。

セグメントが空の場合(例: /shop)でもページがマッチし、デフォルトの動作を実装できます。

なぜ使う?

Optional Catch-allセグメントは、複数のパス構造を1つのページで処理したい場合に役立ちます。これにより、ルート設定を簡略化しつつ、柔軟性を向上させます。

ユースケース1. ECサイトのカテゴリーページ

カテゴリーページでは以下のようなURL構造が一般的です:

  • /shop → すべての商品を表示(ショップのトップページ)。
  • /shop/electronics → エレクトロニクスカテゴリの商品を表示。
  • /shop/electronics/phones → サブカテゴリのスマートフォンを表示。

Optional Catch-allセグメントを使用すると、これらのURLに対して1つのコードで対応できます。

コード例: カテゴリーページの実装

tsx
// app/shop/[[...slug]]/page.tsx
export default function ShopPage({ params }: { params: { slug?: string[] } }) {
  const categoryPath = params.slug?.join(' > ') || '全商品';

  return (
    <div>
      <h1>ショップ: {categoryPath}</h1>
      <p>カテゴリに基づいた商品一覧を表示</p>
    </div>
  );
}

動作例

URLparams.slug表示内容
/shopundefinedショップ: 全商品
/shop/electronics['electronics']ショップ: electronics
/shop/electronics/phones['electronics', 'phones']ショップ: electronics > phones

ユースケース2. 検索ページ

検索ページで以下のようなURL構造を考えます:

  • /search → 検索フォームを表示。
  • /search/keyword → 特定のキーワードで検索結果を表示。
  • /search/keyword1/keyword2 → 複数のキーワードで検索結果を表示。

Optional Catch-allセグメントを使うと、キーワードがない場合(/search)と複数キーワードの場合(/search/keyword1/keyword2)を1つのコードで処理できます。

コード例: 検索ページの実装

tsx
 // app/search/[[...keywords]]/page.tsx
export default function SearchPage({ params }: { params: { keywords?: string[] } }) {
  const searchQuery = params.keywords?.join(', ') || '指定なし';

  return (
    <div>
      <h1>検索結果: {searchQuery}</h1>
      <p>検索条件に基づいた結果を表示</p>
    </div>
  );
}

動作例

URLparams.keywords表示内容
/searchundefined検索結果: 指定なし
/search/nextjs['nextjs']検索結果: nextjs
/search/nextjs/react['nextjs', 'react']検索結果: nextjs, react

Optional Catch-allセグメントのまとめ

Optional Catch-allセグメントは、階層的なルートやデフォルト動作を持つアプリケーションで特に有効です。ECサイトや検索ページ、複数のセクションを持つページでの使用が推奨されます。

  • 使う場面: トップページとサブページを一貫して処理する必要がある場合。
  • メリット: 柔軟性と簡潔なルート管理。

これを理解することで、よりスケーラブルで保守性の高いアプリケーションを構築できます。

記事のまとめ

Dynamic Routesは、Next.jsで動的なデータを扱う際に不可欠な機能です。以下を押さえておきましょう:

  • フォルダ名を角括弧[]で囲むことで動的セグメントを作成。
  • generateStaticParamsを使ってビルド時に静的ルートを生成。
  • Catch-allセグメントやOptional Catch-allセグメントで柔軟なルート設計が可能。

これらを活用することで、スケーラブルで効率的なアプリケーションを構築できます!