本文へ移動
verified onnext@16.3.5react@19
最終検証日 2026-09-26
Next.js道場

next/headers を Client Component で使えない

実際に出るエラー

Error: You're importing a module that depends on "next/headers" into a React Client Component module.
This API is only available in Server Components but one of its parents is marked with "use client",
so this module is also a Client Component.

Cookie やヘッダを読む next/headers を、use client を付けた側へ持ち込んだときに出るエラーです。

読む相手がいない

Cookie もヘッダも、サーバーが要求を受け取って初めて読めるものです。use client を付けたファイルはブラウザにも渡るので、そこから読もうとしても読む相手がいません。

だから、実行してみるまでもなく import の時点で止まります。

'use client'
 
import { cookies } from 'next/headers'
Error: You're importing a module that depends on "next/headers" into a
React Client Component module. This API is only available in Server Components
but one of its parents is marked with "use client", so this module is also a
Client Component.

直接 import していなくても出る

ここが本題です。実機で確かめました。

app/
  Panel.tsx     'use client'。next/headers は書いていない
  session.ts    ここが next/headers を import している
'use client'
 
import { currentUser } from './session'   // ← これだけ

同じエラーになります。use client の印は、そのファイルから import した先へ下向きに広がるからです。session.ts も Client Component 側の一部になります。

印は import の向きに広がる。たどった先まで全部が対象になる
サーバー側に置くもの
cookies() / headers()
DB への問い合わせ
秘密の値
use client から下
Panel.tsx
session.ts(import したので巻き込まれる)

越えられる: 読んだ結果の文字列

越えられない: next/headers そのもの

越えられない: 読む関数ごと渡すこと

直し方

読むのはサーバー、使うのはブラウザに分けます。越えるのは値だけです。

// app/page.tsx(サーバー側のまま)
import { cookies } from 'next/headers'
import { Panel } from './Panel'
 
export default async function Page() {
  const c = await cookies()
  return <Panel name={c.get('user')?.value ?? 'ゲスト'} />
}
// app/Panel.tsx
'use client'
 
export function Panel({ name }: { name: string }) {
  return <button onClick={() => alert(name)}>ようこそ {name} さん</button>
}

実機で確かめました。これでビルドは通ります。

向きが逆の、同じ形のエラー

どちら側のものを、どちら側へ持ち込んだか
持ち込んだもの持ち込んだ先出るエラー
next/headersuse client の側このページ
useStateServer Component の側useState を import できないエラー

言っていることは1つです。境界をまたいで持ち込めるのは値だけで、仕組みそのものは越えられません。もう片方はuseState を import できないエラーにあります。

共通の関数ほど、両側から読まれる

session.ts のような共通の置き場は、いつのまにか両側から読まれます。そのときに気づけるよう、サーバー専用のものには印を付けてください。

import 'server-only'
 
import { cookies } from 'next/headers'

こうしておくと、ブラウザ側から読まれた瞬間にビルドが止まります。詳しくはserver-only と client-only の使い分けにあります。

出典

このページの内容は上記の一次情報を基準に書いています。個人ブログや二次情報を根拠にしていません。

理解できたか試す

では、このコードはどうなりますか。

このモジュールを Client Component から import すると何が起きますか。

この問題を解くこのテーマの問題 3 問