SuperAPI AI 工具集

nextjs-client-cookie-pattern

编程与开发

查看项目

更新于 10-15 15:37

技能介绍

用途

该资料介绍一种 Next.js 编码模式,用于处理「客户端交互后需要设置服务端 Cookie」的场景。典型情况是用户点击按钮(如切换主题、接受 Cookie 横幅、选择语言)后需要写入 Cookie。

为什么要拆成两个文件

资料给出的原因是:客户端组件('use client')可以带 onClick 处理函数;但只有服务端代码才能设置 Cookie(出于安全要求)。因此方案是让客户端组件调用一个设置 Cookie 的服务端操作。

主要能力与使用方式

模式由两个文件组成:

  • 客户端组件(如 app/CookieButton.tsx):带 'use client' 指令,含 onClick 处理函数,导入并调用服务端操作。
  • 服务端操作(如 app/actions.ts):带 'use server' 指令,使用来自 next/headers 的 cookies(),并设置 Cookie。

代码结构如下:

app/
├── CookieButton.tsx    ← 客户端组件
├── actions.ts          ← 服务端操作
└── page.tsx            ← 使用 CookieButton

资料给出的基础实现:

客户端组件:

// app/CookieButton.tsx
'use client';

import { setPreference } from './actions';

export default function CookieButton() {
  const handleClick = async () => {
    await setPreference('dark-mode', 'true');
  };

  return (
    <button onClick={handleClick}>
      Enable Dark Mode
    </button>
  );
}

服务端操作:

// app/actions.ts
'use server';

import { cookies } from 'next/headers';

export async function setPreference(key: string, value: string) {
  const cookieStore = await cookies();

  cookieStore.set(key, value, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'lax',
    maxAge: 60 * 60 * 24 * 365, // 1 year
  });
}

资料强调 TypeScript 中不要使用 any 类型,并给出正确写法示例(参数类型标注为 string)。

示例场景

资料提供了若干现实示例:主题切换(ThemeToggle 配合 setTheme)、接受 Cookie 横幅(CookieBanner 配合 acceptCookies)、语言偏好(LanguageSelector 配合 setLanguage)、表单提交(使用 form action 与 FormData 的 savePreferences)、以及设置 Cookie 后重定向(login 中先设置 session Cookie,再调用 redirect('/dashboard'))。

Cookie 选项

资料列出可用的设置项:

cookieStore.set('name', 'value', {
  httpOnly: true,    // 阻止 JavaScript 访问(安全)
  secure: true,      // 仅通过 HTTPS 发送
  sameSite: 'lax',   // CSRF 防护
  maxAge: 3600,      // 1 小时后过期(秒)
  path: '/',         // 在所有路由可用
});

与其他方案的比较

资料说明客户端组件不能直接设置 Cookie,因为运行在浏览器中且现代浏览器出于安全限制 Cookie 操作;服务端操作在服务端运行,允许设置 Cookie。资料也给出路由处理器(API 路由)的替代写法,并列出优先使用服务端操作的理由:类型更安全、样板代码更少、与表单集成更好、更易测试。

读取 Cookie

在服务端组件中,通过 next/headers 的 cookies() 读取(如 cookieStore.get('theme')?.value || 'light')。在客户端组件中不能使用 next/headers,资料建议改用 document.cookie 或状态管理库,并给出用 useEffect 读取 document.cookie 的示例。

限制与注意事项

资料提醒:next/headers 不能在客户端组件中使用;Next.js 15+ 中需要 await cookies()。文档未说明具体版本兼容范围、性能影响或收费相关信息。