Dynamic Routes とは

Dynamic Routes は、Next.js でルーティングを動的に生成する機能です。これにより、静的なルーティングでは表現できない、可変的なパスを取り扱うことができます。たとえば、ブログ記事のように、記事ごとに異なる URL を生成したい場合に Dynamic Routes を利用します。

ルーティングの基本

Next.js では、pages ディレクトリ内に配置されたファイルをもとに、自動的にルーティングが生成されます。例えば、pages/blog.tsx というファイルを作成すると、/blog という URL が生成されます。

Dynamic Routes の実装方法

Dynamic Routes を実装するには、ファイル名に角括弧([])を使用し、その中にパラメータ名を指定します。例えば、pages/blog/[id].tsx というファイルを作成すると、/blog/:id のような動的な URL が生成されます。ここで、:id の部分は実際の記事 ID に置き換えられます。

動的パスの取得

動的パスを取得するには、getStaticPaths という非同期関数を実装します。この関数は、ページを生成する際に利用可能なパスの一覧を返す役割があります。以下に、getStaticPaths の実装例を示します。

// pages/blog/[id].tsx

import { GetStaticPaths } from 'next'

type Post = {
  id: string
  title: string
}

const posts: Post[] = [
  { id: '1', title: '記事 1' },
  { id: '2', title: '記事 2' },
  // ...
]

export const getStaticPaths: GetStaticPaths = async () => {
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))

  return {
    paths,
    fallback: false,
  }
}

ここでは、posts という配列に各記事の情報を格納し、getStaticPaths 関数内で各記事のパスを生成しています。fallback は、生成されていないパスへのアクセス時の挙動を制御するオプションで、false の場合は 404 ページが表示されます。

動的パスのデータ取得

動的パスごとにデータを取得するには、getStaticProps という非同期関数を実装します。この関数は、ページを生成する際に、動的パスに関連するデータを取得する役割があります。以下に、getStaticProps の実装例を示します。

// pages/blog/[id].tsx

import { GetStaticProps, GetStaticPaths } from 'next'

type Post = {
  id: string
  title: string
}

type Props = {
  post: Post
}

const posts: Post[] = [
  { id: '1', title: '記事 1' },
  { id: '2', title: '記事 2' },
  // ...
]

export const getStaticPaths: GetStaticPaths = async () => {
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))

  return {
    paths,
    fallback: false,
  }
}

export const getStaticProps: GetStaticProps<Props> = async (context) => {
  const id = context.params?.id as string
  const post = posts.find((p) => p.id === id)

  if (!post) {
    return {
      notFound: true,
    }
  }

  return {
    props: {
      post,
    },
  }
}

const BlogPost = ({ post }: Props) => {
  return (
    <div>
      <h1>{post.title}</h1>
      {/* 本文などのコンテンツを表示 */}
    </div>
  )
}

export default BlogPost

ここでは、getStaticProps 関数内で動的パスに関連するデータを取得しています。context.params?.id を使って動的パスのパラメータ(この例では記事 ID)を取得し、それをもとに記事データを検索しています。見つかったデータは props を介してコンポーネントに渡されます。

TypeScript との組み合わせ

Dynamic Routes の実装では、GetStaticPathsGetStaticProps の型定義を利用することで、型安全性を保ちながらコーディングができます。以下では、実装例を振り返りながら TypeScript との組み合わせのポイントを説明します。

型定義の適用

GetStaticPaths 関数の型定義には GetStaticPaths を、GetStaticProps 関数の型定義には GetStaticProps を適用します。これにより、関数の実装が正しいかどうかが型チェックされます。

export const getStaticPaths: GetStaticPaths = async () => {
  // ...
}

export const getStaticProps: GetStaticProps<Props> = async (context) => {
  // ...
}

Props 型の定義

ページコンポーネントで使用するプロパティの型を定義し、GetStaticProps とコンポーネントに適用します。これにより、データ取得とコンポーネントのプロパティが一致しているかどうかが型チェックされます。

type Props = {
  post: Post
}

export const getStaticProps: GetStaticProps<Props> = async (context) => {
  // ...
}

const BlogPost = ({ post }: Props) => {
  // ...
}

パラメータの型チェック

getStaticProps 内で、context.params からパラメータを取得する際には、型アサーションを使用して適切な型に変換します。これにより、パラメータを使用するコードが型安全になります。

const id = context.params?.id as string

まとめ

この記事では、Next.js の Dynamic Routes と TypeScript を組み合わせた実装方法について解説しました。Dynamic Routes を使うことで、動的な URL を持つページを生成することができます。また、TypeScript の型定義を適用することで、型安全性を保ちながらコーディングができます。

実装のポイントは以下の通りです。

  1. ファイル名に角括弧([])を使用して動的パスを定義する。
  2. getStaticPaths 関数を実装して、利用可能なパスの一覧を返す。
  3. getStaticProps 関数を実装して、動的パスに関連するデータを取得する。
  4. TypeScript の型定義を適用して、型安全性を保つ。

これらの知識を活用して、柔軟なルーティングを実現する Next.js アプリケーションを構築してください。