You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js 14 App目录登录设Cookie刷新触发Hydration Failed问题求助

Next.js 14 登录Cookie设置与Hydration Failed错误解决

一、错误原因

刷新页面触发Hydration Failed,核心是服务器端渲染(SSR)与客户端Hydration阶段的内容不一致:客户端设置Cookie后,当前页面的服务器渲染结果(未读取到Cookie)和客户端实际状态(已存在Cookie)冲突,导致页面结构不匹配。

二、解决方案

1. 客户端设置Cookie的优化

使用js-cookie设置Cookie后,必须立即跳转页面,让服务器重新渲染新页面(此时服务器能读取到新Cookie),避免当前页面的Hydration冲突:

'use client'
import Cookies from 'js-cookie'
import { useRouter } from 'next/navigation'

const handleFinish = async (e: any) => {
  const res = await api.post('/Auth/user/signIn', e)
  if (!res || res.status !== 200) return
  
  Cookies.set('access_token', res.data.token, {
    secure: process.env.NODE_ENV === 'production', // 本地开发关闭secure,否则http环境下Cookie无法写入
    expires: 12000,
    path: '/' // 确保全站可访问
  })
  toast.success(res.data.message, { position: 'bottom-center' })
  router.replace('/') // 跳转页面,触发服务器重新渲染
}

2. 服务器组件读取Cookie

服务器组件通过headers()函数直接读取请求头中的Cookie:

import { headers } from 'next/headers'

export default async function ServerPage() {
  const cookieStr = headers().get('cookie')
  let accessToken = null

  if (cookieStr) {
    const cookies = Object.fromEntries(
      cookieStr.split('; ').map(item => item.split('='))
    )
    accessToken = cookies.access_token
  }

  return <div>{accessToken ? '已登录' : '未登录'}</div>
}

3. 客户端组件读取Cookie

客户端组件直接用js-cookie或document.cookie读取:

'use client'
import Cookies from 'js-cookie'

export default function ClientComponent() {
  const accessToken = Cookies.get('access_token')
  return <div>{accessToken ? '已登录' : '未登录'}</div>
}

4. 避免Hydration冲突的关键规则

如果必须在当前页面根据登录状态渲染内容,需用useEffect在客户端Hydration完成后再读取Cookie,避免服务器与客户端渲染结果不一致:

'use client'
import { useState, useEffect } from 'react'
import Cookies from 'js-cookie'

export default function LoginStatus() {
  const [isLoggedIn, setIsLoggedIn] = useState(false)

  useEffect(() => {
    const token = Cookies.get('access_token')
    setIsLoggedIn(!!token)
  }, [])

  return <div>{isLoggedIn ? '已登录' : '未登录'}</div>
}

5. 更可靠的服务器端设置Cookie方案

将登录请求转发到Next.js API路由,在服务器端设置Cookie,确保服务器和客户端能同时获取到:

创建API路由 app/api/auth/signin/route.ts

import { NextResponse } from 'next/server'

export async function POST(request: Request) {
  const body = await request.json()
  // 调用第三方登录接口
  const authRes = await fetch(`${process.env.AUTH_API_BASE}/Auth/user/signIn`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body)
  })

  if (!authRes.ok) {
    return NextResponse.json({ error: '登录失败' }, { status: authRes.status })
  }

  const data = await authRes.json()
  const response = NextResponse.json({ message: data.message })

  // 服务器端设置Cookie
  response.cookies.set({
    name: 'access_token',
    value: data.token,
    secure: process.env.NODE_ENV === 'production',
    expires: new Date(Date.now() + 12000 * 24 * 60 * 60 * 1000), // 转换为日期对象
    path: '/',
    sameSite: 'strict'
    // 若不需要客户端读取Cookie,可添加 httpOnly: true 提升安全性
  })

  return response
}

客户端调用该API路由

'use client'
import { useRouter } from 'next/navigation'

const handleFinish = async (e: any) => {
  const res = await fetch('/api/auth/signin', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(e)
  })

  if (!res.ok) return
  const data = await res.json()
  toast.success(data.message, { position: 'bottom-center' })
  router.replace('/')
}

内容的提问来源于stack exchange,提问作者Muhammad Yuldashev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 07:42:24