🍪

【Next.js 15】Server Actions で cookie を利用する

2024/11/19に公開

当時 Next.js の最新バージョンだった v12 で作ったサイトが時代の変化に取り残され化石と化していたので、今さらながらアップデートを行いました。
大きなトピックは Pages Router から App Router への移行でしたが、他の機能として個人的に嬉しかった cookie の標準サポートについて、躓いたポイントをメモとして残します。

https://nextjs.org/docs/app/api-reference/functions/cookies

まずは cookie を設定する関数を用意します。これは Server Actions のため、サーバーコンポーネントで準備する必要があります。

src/liblaries/cookie.ts
'use server';

import { cookies } from 'next/headers';

export const setCookie: (name: string, value: string) => Promise<void> = async (
  name: string,
  value: string
) => {
  const cookieStore = await cookies();

  cookieStore.set({ name, value });
};

クライアントコンポーネントで呼び出した場合、以下のようなエラーが発生します。

next/headers からの cookies の import は、サーバーコンポーネントしか行えないようですね。

2. [クライアントコンポーネント] 用意した関数を呼び出し、cookie を設定する

  1. で用意した setCookie() は、クライアントコンポーネントで呼び出す必要があります。
src/app/components/Container.tsx
'use client';

import { setCookie } from '@/libraries/cookie';

export const Container = () => {
  ...
  await setCookie('name', 'value');
  ...

Server Action そのものはサーバーコンポーネントでもクライアントコンポーネントでも呼び出すことが可能ですが、await cookies().set に関してはこの限りではないようです。
サーバーコンポーネントで呼び出した場合、以下のようなエラーが発生します。

例えば、cookie に登録してある情報を meta タグ内で用いる、といったこともここでは簡単にできます。

'use server';

import { Metadata } from 'next';
import { cookies } from 'next/headers';
import { Container } from '@/components/Container';

export async function generateMetadata(): Promise<Metadata> {
  const cookieStore = await cookies();
  const title = cookieStore.get('title')?.value;
  const description = cookieStore.get('description')?.value;

  return { title, description };
}

export const HomePage = () => (
  <Container>
...

クライアントコンポーネントで呼び出した場合、1と同じエラーが発生します。

おわりに

慣れるとなんてことない利用法なのかもしれませんが、使わないうちに忘れてしまいそうなので、発生するエラーを含めてまとめてみました。
どなたかのお力になれれば幸いです。

Discussion