Skip to content

データの取得と表示

公開日:December 10, 2024更新日:December 10, 2024
NextjsTypeScriptCoding📄

この章では、Next.jsアプリケーションでデータを取得し、ページに表示する方法について学びます。Next.jsには、静的生成(getStaticProps)、サーバーサイドレンダリング(getServerSideProps)、動的ページ生成(getStaticPaths)など、様々なデータ取得の方法が用意されています。それぞれの特徴と使い分けを理解し、効率的なデータ取得と表示を実装しましょう。

1. getStaticPropsによる静的データの取得

getStaticPropsは、ビルド時にデータを取得し、静的なHTMLを生成するために使用します。外部APIやヘッドレスCMSなどからデータを取得して、静的なページを生成するのに適しています。

ビルド時のデータ取得

getStaticPropsは、Next.jsのビルドプロセス中に実行されます。つまり、next buildコマンドを実行したときに、データが取得され、そのデータを使って静的なHTMLが生成されます。

APIからのデータ取得

getStaticPropsを使って、外部APIからデータを取得してみましょう。例として、JSONPlaceholderというダミーAPIを使って、ブログ記事の一覧を取得します。

まず、pages/posts.tsxを作成し、以下のコードを記述します。

tsx
// pages/posts.tsx

import type { GetStaticProps } from 'next';

interface Post {
  id: number;
  title: string;
  body: string;
}

interface Props {
  posts: Post[];
}

const PostsPage: React.FC<Props> = ({ posts }) => {
  return (
    <div>
      <h1>Posts</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>
            <h2>{post.title}</h2>
            <p>{post.body}</p>
          </li>
        ))}
      </ul>
    </div>
  );
};

export const getStaticProps: GetStaticProps<Props> = async () => {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts');
  const posts: Post[] = await res.json();

  return {
    props: {
      posts,
    },
  };
};

export default PostsPage;

ポイントは、getStaticProps関数をエクスポートしているところです。この関数は、Next.jsのビルド時に実行され、propsを返します。propsに指定したデータは、ページのコンポーネント(ここではPostsPage)に渡されます。

取得したデータの表示

PostsPageコンポーネントでは、getStaticPropsから渡されたpostsデータを表示しています。

tsx
const PostsPage: React.FC<Props> = ({ posts }) => {
  return (
    <div>
      <h1>Posts</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>
            <h2>{post.title}</h2>
            <p>{post.body}</p>
          </li>
        ))}
      </ul>
    </div>
  );
};

posts配列をmapメソッドでループ処理し、各記事のタイトルと本文を表示しています。

npm run devで開発サーバーを起動し、http://localhost:3000/postsにアクセスすると、JSONPlaceholder APIから取得した記事の一覧が表示されます。

2. getServerSidePropsによるサーバーサイドレンダリング

getServerSidePropsは、リクエストごとにサーバー側でデータを取得し、ページをレンダリングするために使用します。ユーザーごとに異なるデータを表示する場合や、常に最新のデータを取得する必要がある場合に適しています。

リクエストごとのデータ取得

getServerSidePropsは、ページへのリクエストがあるたびに、サーバー側で実行されます。そのため、常に最新のデータを取得して、ページをレンダリングできます。

ユーザー認証やセッションデータの利用

getServerSidePropsでは、リクエストオブジェクトにアクセスできるため、ユーザーの認証情報やセッションデータなどを取得できます。これを利用して、ユーザーごとに異なるデータを表示したり、認証が必要なページを実装したりできます。

例として、リクエストごとにランダムな数字を取得して表示するページを作成してみましょう。pages/random.tsxを作成し、以下のコードを記述します。

tsx
// pages/random.tsx

import type { GetServerSideProps } from 'next';

interface Props {
  randomNumber: number;
}

const RandomPage: React.FC<Props> = ({ randomNumber }) => {
  return (
    <div>
      <h1>Random Number</h1>
      <p>The random number is: {randomNumber}</p>
    </div>
  );
};

export const getServerSideProps: GetServerSideProps<Props> = async () => {
  const randomNumber = Math.random();

  return {
    props: {
      randomNumber,
    },
  };
};

export default RandomPage;

getServerSideProps関数内で、Math.random()を使ってランダムな数字を生成し、propsとして返しています。このrandomNumberは、RandomPageコンポーネントに渡され、ページに表示されます。

http://localhost:3000/randomにアクセスするたびに、異なるランダムな数字が表示されます。

3. getStaticPathsによる動的ページの生成

getStaticPathsは、getStaticPropsと組み合わせて使用し、動的なパスを持つページを静的に生成するために使用します。例えば、ブログ記事の詳細ページなど、URLにIDなどのパラメータが含まれるページを生成するのに適しています。

動的ルートとデータに基づいたページ生成

getStaticPathsでは、生成するページのパスの一覧を返します。Next.jsは、このパスの一覧に基づいて、静的なHTMLを生成します。

getStaticPropsとの組み合わせ

getStaticPathsは、通常getStaticPropsと組み合わせて使用します。getStaticPathsでパスの一覧を生成し、getStaticPropsで各パスに対応するデータを取得します。

例として、先ほどのJSONPlaceholder APIを使って、ブログ記事の詳細ページを静的に生成してみましょう。

まず、pages/posts/[id].tsxを作成し、以下のコードを記述します。

tsx
// pages/posts/[id].tsx

import type { GetStaticProps, GetStaticPaths } from 'next';

interface Post {
  id: number;
  title: string;
  body: string;
}

interface Props {
  post: Post;
}

const PostDetailPage: React.FC<Props> = ({ post }) => {
  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
    </div>
  );
};

export const getStaticPaths: GetStaticPaths = async () => {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts');
  const posts: Post[] = await res.json();

  const paths = posts.map((post) => ({
    params: { id: post.id.toString() },
  }));

  return {
    paths,
    fallback: false, // 存在しないパスには404を返す
  };
};

export const getStaticProps: GetStaticProps<Props> = async ({ params }) => {
  const id = params?.id;
  const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`);
  const post: Post = await res.json();

  return {
    props: {
      post,
    },
  };
};

export default PostDetailPage;

getStaticPathsでは、まずJSONPlaceholder APIから記事の一覧を取得し、paths配列を生成しています。paths配列には、生成するページのパスの一覧が含まれます。ここでは、各記事のIDをパスパラメータとして指定しています。

fallback: falseは、pathsで指定されていないパスにアクセスがあった場合に、404ページを表示する設定です。

getStaticPropsでは、paramsオブジェクトからidを取得し、そのIDに対応する記事データを取得しています。取得したデータは、propsとしてPostDetailPageコンポーネントに渡されます。

http://localhost:3000/posts/1などにアクセスすると、対応する記事の詳細ページが表示されます。