Next.js服务端组件调用服务端Action修改Cookie失败求助
问题分析与解决
你遇到的问题核心是:在Next.js服务端组件(RSC)的渲染流程中直接调用带'use server'标记的函数清除Cookie,这违反了Next.js的规则——修改Cookie的操作仅允许在用户交互触发的Server Action或Route Handler中执行,不能在组件初始化/渲染阶段直接调用。
原代码的错误点:logout函数虽标记了'use server',但你是在组件渲染逻辑(检测接口错误时)直接调用它,这种服务器端同步执行的方式不属于允许修改Cookie的场景,因此触发报错。
两种正确实现方式
方式一:自动检测令牌失效并登出(渲染时触发)
创建专门处理登出的Route Handler,将清除Cookie和重定向逻辑放在这里:
- 创建文件
app/api/logout/route.ts:
import { cookies } from 'next/headers'; import { redirect } from 'next/navigation'; export async function GET() { // 清除会话令牌Cookie cookies().delete('access_token'); // 重定向到登录页 redirect('/login'); }
- 修改Home组件的错误处理逻辑,直接重定向到该Route:
export default async function Home() { const result = await getClient().query(PokemonsQuery, {}).toPromise(); // 检测到令牌失效时,跳转到登出接口处理 if(result.error && result.error.networkError){ redirect('/api/logout'); } return ( <main> <h1>This is rendered as part of an RSC</h1> <ul> <div> <p>id: {result.data.me.id}</p> <p>username: {result.data.me.username}</p> <p>roles: {result.data.me.roles.join(', ')}</p> <p>createdAt: {result.data.me.createdAt}</p> <p>updatedAt: {result.data.me.updatedAt}</p> </div> </ul> </main> ); }
方式二:用户手动触发登出(按钮点击)
如果需要用户主动点击按钮登出,确保Server Action由用户交互触发:
修改Home组件,添加登出按钮并正确绑定Server Action:
export default async function Home() { const result = await getClient().query(PokemonsQuery, {}).toPromise(); // 标记为Server Action的登出函数 async function logout() { 'use server'; cookies().delete('access_token'); redirect('/login'); } // 自动登出逻辑(可选,需保留则用方式一的Route Handler) if(result.error && result.error.networkError){ redirect('/api/logout'); } return ( <main> <h1>This is rendered as part of an RSC</h1> <ul> <div> <p>id: {result.data.me.id}</p> <p>username: {result.data.me.username}</p> <p>roles: {result.data.me.roles.join(', ')}</p> <p>createdAt: {result.data.me.createdAt}</p> <p>updatedAt: {result.data.me.updatedAt}</p> </div> </ul> {/* 用户点击触发Server Action */} <button onClick={logout}>登出</button> </main> ); }
内容的提问来源于stack exchange,提问作者vivek gupta
相关产品推荐
相关产品推荐

