NextJS中RootLayout获取Cookie较Middleware延迟一次刷新的问题
我最近在开发NextJS时遇到了一个异常:因为无法从RootLayout组件中获取contextSpec(请求/响应对象),所以我通过Middleware设置Cookie,再结合Next的Cookie库在RootLayout中恢复用户会话。但出现了问题:Middleware设置新Cookie后,RootLayout获取到的是旧版本;删除Cookie后,RootLayout仍能读取到该Cookie。只有刷新页面后两者才同步,RootLayout的Cookie总是滞后一次请求。简化测试后,我在Middleware里设置含随机值的Cookie,RootLayout还是只能拿到上一次的随机值。
相关代码如下:
middleware.ts
export async function middleware(request: NextRequest) { const token = { email: Math.random() }; const response = NextResponse.next(); response.cookies.set("my_custom_cookie", JSON.stringify(token)); console.log("EMAIL FROM MIDDLEWARE = ", token.email); return response; }
RootLayout.tsx
export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { const cookieStore = cookies(); const idTokenCookie = cookieStore.get("my_custom_cookie"); const idToken = idTokenCookie ? JSON.parse(idTokenCookie.value) : null; console.log("EMAIL FROM ROOT LAYOUT = ", idToken?.email); const user = { email: idToken?.email, }; return ( <html suppressHydrationWarning={true} lang="fr"> <body className={inter.className}> <AuthProvider initialUser={user}> {children} </AuthProvider> </body> </html> ); }
异常原因
这个问题的核心是Next.js的渲染时序和Cookie传递机制导致的:
- 服务端渲染时序问题:当请求到达时,Next.js会优先执行RootLayout的服务端渲染逻辑,此时它读取的是请求中携带的原始Cookie(也就是上一次请求留下的旧值)。而Middleware是在RootLayout渲染完成后,才会处理响应并设置新的Cookie到响应头中——这个新Cookie只会在浏览器收到响应后被保存,要等到下一次请求才会被携带到服务器。
- 客户端导航复用状态:如果是通过
next/link进行客户端导航,Next.js会复用现有客户端的状态,RootLayout不会重新执行服务端渲染逻辑,自然也不会读取新的Cookie值,直到页面刷新触发全新的HTTP请求。
简单来说:RootLayout读取的是当前请求的入站Cookie,而Middleware设置的是出站响应Cookie,两者不在同一个请求周期内生效,所以会出现RootLayout的Cookie总是滞后一次请求的现象。
内容的提问来源于stack exchange,提问作者Ludovic Vue
相关产品推荐
相关产品推荐

