【Next.js】cookies 関数を使って Cookie を操作する
はじめに
業務において Next.js のcookies
関数を使用して Cookie を作成・取得するという機会があったので、実装を行うにあたって参考にした公式ドキュメントをもとに、Next.js での Cookie の扱い方をまとめました。
参考にしたドキュメントはこちら👇
Cookie について
Cookie とはサーバーからブラウザに送られる小さな文字列データです。ブラウザは Cookie を保存・新規作成・変更などを行うことができます。さらにはその後リクエストされたときに同じサーバーに送り返したりもできます。
Cookie は Web アプリにおいて次の3つの用途で使われることが多いです。
1. セッション管理:ユーザーのログイン状態など
2. パーソナライズ:表示言語や UI テーマなど
3. トラッキング:ユーザーの行動記録および分析
Next.js の cookies 関数
Next.js では Cookie の作成・取得・変更・削除を行うことができるcookies
関数が提供されています。
cookies
関数を利用すると、サーバーコンポーネントから HTTP リクエストの Cookie を読みとったり、Server Actions や Route API で HTTP レスポンスに Cookie を書き込むことができます。
cookies
関数は返り値を事前に知ることができない動的関数です。つまり、layout
やpage
でこの関数を利用すると、そのページはリクエスト時に動的にレンダリングされます。あくまでサーバーでの処理を行うための関数であり、クライアントサイドでの処理には基本的には使えません。クライアント側で Cookie を扱う場合、以下のようなライブラリが提供されています。
cookies
関数のメソッド
cookies().get(name)
Cookie の名前を引数に取り、名前と値のセットのオブジェクトを返します。name に対応する Cookie が存在しない場合は、undefined
を返します。
もし 名前に対応する Cookie が複数存在する場合は、最初に見つかったものを返します。
import { cookies } from 'next/headers'
export default function Page() {
const cookieStore = cookies()
const theme = cookieStore.get('theme')
console.log(theme) // { name: 'theme', value: 'dark' }
return ...
}
cookies().getAll(name)
cookies.get()
に似ていますが、get()
と異なるのは引数に指定されたname
と一致する全ての名前と値のオブジェクトを返すことです。もし名前が指定されない場合は、名前に限らず全ての Cookie を返します。
import { cookies } from 'next/headers'
export default function Page() {
const cookieStore = cookies()
// 引数が指定されていないので全ての Cookie が走査される
return cookieStore.getAll().map((cookie) => (
<div key={cookie.name}>
<p>Name: {cookie.name}</p>
<p>Value: {cookie.value}</p>
</div>
))
}
cookies().has(name)
name
を引数に取り、その名前の Cookie が存在するかどうかをboolean
で返します。
import { cookies } from 'next/headers'
export default function Page() {
const cookieStore = cookies()
const hasCookie = cookieStore.has('theme')
console.log(hasCookie) // true or false
return '...'
}
cookies().set(name, value, options)
名前と値とオプションを引数に取り、送信リクエストの Cookie を設定します。
HTTP ではストリーミングが始まった後に Cookie をセットすることはできません。したがって、set()
は Server Components か Route Handler でのみ利用できます。どちらにしろサーバー側のエンドポイントに対してリクエストを送る形で Cookie をセットしなければいけないということですね。
以下のコードは Server Actions で Cookie を設定する例です。
'use server'
import { cookies } from 'next/headers'
async function create(data) {
cookies().set('name', 'lee')
// or
cookies().set('name', 'lee', { secure: true })
// or
cookies().set({
name: 'name',
value: 'lee',
httpOnly: true,
path: '/',
})
}
こちらの記事ではちょうど Cookie を例に2つの方法の説明やどちらを選べばいいのかを詳細に説明されているので、気になる方はぜひ目を通してみてください。
Cookie の削除
Cookie の削除にはいくつかの方法があります。ただし、いずれにしても set()
と同じように Server Actions もしくは Route Handler で行う必要があります。
cookies().delete(name)
name
を引数に渡して明示的に削除する方法です。
'use server'
import { cookies } from 'next/headers'
async function delete(data) {
cookies().delete('name')
}
cookies().set(name, '')
別の方法として、同じ名前で空文字の値を持つ Cookie を作成することで既存の Cookie の値を上書きすることもできます。
'use server'
import { cookies } from 'next/headers'
async function delete(data) {
cookies().set('name', '')
}
他にも以下のようなやり方もありますが、登場頻度は上の2つほどはないかなと思います。
-
cookies().set(name, value, { maxAge: 0 })
:maxAge
プロパティの値を0にすることで即座に削除する方法 -
cookies().set(name, value, { expires: timestamp })
:expires
プロパティの値をどの時点でもいいので過去に設定することで削除する方法
おわりに
最後まで読んでいただきありがとうございます。
Cookie の基本的な概念や Next.js のcookies
関数のAPIは意外とシンプルですが、これを実装にまで落とし込むとなるとつまづくところもあり、まだまだコードを書く量が圧倒的に足りていないと感じました。Cookie を始め Server Action や RCS については @Leerob など Vercel の内部のエンジニアが YouTube で発信してくれているのでそれらを参考にしつつ、これからも学習を続けていきたいです。
Discussion