この章では、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などにアクセスすると、対応する記事の詳細ページが表示されます。