3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Next.js 13.4 App Router のレンダリング実装方法

Posted at

はじめに

以下の記事では、Pages Router のレンダリング実装方法について記載しました。

今回は App Router のレンダリング実装方法について記載していきます。

開発環境

開発環境は以下の通りです。

  • Windows11
  • VSCode
  • Next.js 13.4.7
  • React 18.2.0
  • TypeScript 5.1.3

プロジェクト作成

まずは以下のコマンドを実行して、プロジェクトを作成します。

npx create-next-app@latest

インストール中にプロンプトが表示されます。No / Yes はすべてデフォルト値を選択します。

image.png

インストールが完了するとプロジェクトファイルが作成されます。
image.png

Client 側でのレンダリング

App Router では、Server Component と Client Component というようにコンポーネント単位でレンダリングの種類を選択できるようになりました。デフォルトでは、Server Component が利用されます。そのため、Client Component を利用するときは、"use client" とファイルに記載する必要があります。

例えば、SWR を利用してクライアント側で、データを取得したい場合、以下のように記載します。

src/app/client-side-rendering/page.tsx
"use client";

import { SAMPLE_API_ENDPOINT } from "@/api";
import { FetchedRandomJoke } from "@/components/FetchedRandomJoke";
import { RandomJoke } from "@/types";
import Head from "next/head";
import useSWR from "swr";
export const TITLE = "Client-Side Rendering (CSR)";

export default function ClientSideRendering() {
  const { data: randomJoke } = useSWR<RandomJoke>(SAMPLE_API_ENDPOINT, fetcher);

  return (
    <>
      <Head>
        <title>{TITLE}</title>
      </Head>
      <h1>{TITLE}</h1>
      <p>Data fetched on the client-side only.</p>
      <FetchedRandomJoke randomJoke={randomJoke} />
    </>
  );
}

async function fetcher() {
  const response = await fetch(SAMPLE_API_ENDPOINT);
  const randomJoke = await response.json();

  return randomJoke;
}

image.png

"use client" を記載しないと、以下のようにエラーになります。
image.png

Dynamic Data Fetching

サーバー側でレンダリング(データ取得)する手法として、Dynamic Data Fetching と Static Data Fetching の2種類あります。
Dynamic Data Fetching を利用する場合、fetch の第二引数に await fetch(SAMPLE_API_ENDPOINT, { cache: "no-store" }); を追加します。

src/app/dynamic-data-fetching/page.tsx
import Head from "next/head";
import { RandomJoke } from "@/types";
import { SAMPLE_API_ENDPOINT } from "@/api";
import { FetchedRandomJoke } from "@/components/FetchedRandomJoke";

export const TITLE = "Dynamic Data Fetching";

export default async function DynamicDataFetching() {
  const randomJoke = await getRandomJoke();

  return (
    <>
      <Head>
        <title>{TITLE}</title>
      </Head>
      <h1>{TITLE}</h1>
      <p>
        Data fetched on the server-side at <b>each</b> request before sending to
        the client.
      </p>
      <FetchedRandomJoke randomJoke={randomJoke} />
    </>
  );
}

export async function getRandomJoke(): Promise<RandomJoke> {
  const response = await fetch(SAMPLE_API_ENDPOINT, { cache: "no-store" });
  const randomJoke = await response.json();

  return randomJoke;
}

Static Data Fetching

Static Data Fetching を利用する場合、fetch の第二引数には何も加える必要はありません。

src/app/dynamic-data-fetching/page.tsx
import Head from "next/head";
import { RandomJoke } from "@/types";
import { SAMPLE_API_ENDPOINT } from "@/api";
import { FetchedRandomJoke } from "@/components/FetchedRandomJoke";

export const TITLE = "Static Data Fetching";

export default async function StaticDataFetching() {
  const randomJoke = await getRandomJoke();

  return (
    <>
      <Head>
        <title>{TITLE}</title>
      </Head>
      <h1>{TITLE}</h1>
      <p>
        Data fetched at <b>build-time</b> on the server-side before sending to
        the client.
      </p>
      <FetchedRandomJoke randomJoke={randomJoke} />
    </>
  );
}

export async function getRandomJoke(): Promise<RandomJoke> {
  const response = await fetch(SAMPLE_API_ENDPOINT);
  const randomJoke = await response.json();

  return randomJoke;
}

fetch の第二引数を { next: { revalidate: 10 } } のようにすると、データを再取得する間隔を指定することができます。

参考

3
2
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
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?