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

Next.js设置Cookie报useContext空值读取错误如何解决

问题根因

触发报错的核心原因是违反React Hooks调用规则+运行环境混用,和React版本、多副本问题无关:

  • [...nextauth].js是Next.js服务端API路由,代码运行在Node.js服务端,不存在React组件渲染上下文
  • 普通工具函数AuthReducer不属于React函数组件/自定义Hook,却在内部调用了useCookies这个React Hook,还将该函数放到服务端的NextAuth回调中执行,完全不符合Hooks的调用要求
  • 错误混用客户端Cookie Hook和服务端逻辑:react-cookie提供的Hook仅能在客户端组件环境运行,根本无法在NextAuth的服务端回调中执行
正确实现方案

不需要额外编写reducer手动调用Cookie库,NextAuth本身原生支持自定义Cookie配置,也支持持久化存储后端返回的自定义业务token,根据需求选对应方案即可。

方案1:使用NextAuth原生配置自定义Cookie(推荐)

直接在NextAuth初始化配置中添加cookies字段,即可全局修改NextAuth下发所有Cookie的属性,同时可以通过回调把后端返回的业务token存在NextAuth内置的JWT/Session中,不需要单独维护额外Cookie:

// pages/api/auth/[...nextauth].js
import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import axios from "axios";

export default NextAuth({
  providers: [
    GoogleProvider({
      clientId: process.env.cid,
      clientSecret: process.env.sid,
    }),
  ],
  // 自定义NextAuth内置Cookie规则
  cookies: {
    sessionToken: {
      name: "next-auth.session-token",
      options: {
        httpOnly: true,
        sameSite: "lax",
        path: "/",
        secure: process.env.NODE_ENV === "production",
        maxAge: 3600 * 24, // 自定义1天过期时间
      }
    },
    // csrfToken、callbackUrl等其他内置Cookie也可在此处修改配置
  },
  callbacks: {
    // 首次登录时拉取后端业务token,存入JWT
    async jwt({ token, account }) {
      if (account?.provider === "google") {
        const apiRes = await axios.post("http://localhost:5000/user/googlelogin", {
          // 仅传必要字段,不要明文传输完整用户敏感信息
          providerAccountId: account.providerAccountId,
          email: account.email,
          name: account.name,
        });
        token.customBusinessToken = apiRes.data.token;
      }
      return token;
    },
    // 将JWT中的自定义字段透传给客户端可访问的session
    async session({ session, token }) {
      session.userToken = token.customBusinessToken;
      return session;
    },
    async signIn({ profile, account }) {
      if (account.provider === "google") {
        return !!profile.email_verified;
      }
      return true;
    }
  },
});

方案2:服务端回调中下发额外自定义Cookie

如果确实需要下发完全独立的自定义业务Cookie,不要使用react-cookie的Hook,直接在NextAuth处理函数中拿到请求/响应对象,用服务端兼容的Cookie工具操作即可:

  1. 先删除原有写了Hook逻辑的auth.js文件,该文件完全不符合Hook调用规则,无保留价值
  2. 重写NextAuth路由处理逻辑:
// pages/api/auth/[...nextauth].js
import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import axios from "axios";
import { setCookie } from 'cookies-next';

// 导出带req/res上下文的处理函数
export default async function authHandler(req, res) {
  return NextAuth(req, res, {
    providers: [
      GoogleProvider({
        clientId: process.env.cid,
        clientSecret: process.env.sid,
      }),
    ],
    callbacks: {
      async signIn({ account, profile }) {
        if (account.provider === "google") {
          const apiRes = await axios.post("http://localhost:5000/user/googlelogin", {
            object: profile,
          });
          // 服务端环境直接调用setCookie,传入req/res即可,不需要Hook
          setCookie("user", JSON.stringify(apiRes.data.token), {
            req,
            res,
            path: "/",
            maxAge: 3600 * 24,
            sameSite: "lax",
            httpOnly: true, // 存储token的敏感Cookie建议开启httpOnly,降低XSS窃取风险
          });
          return !!profile.email_verified;
        }
        return true;
      },
    },
  })
}

注意:useCookies这类React Hook 仅允许在React函数组件、自定义Hook的顶层作用域调用,禁止在普通工具函数、服务端代码、条件分支、循环逻辑中调用,否则必然触发Hook规则报错。

内容的提问来源于stack exchange,提问作者NRA 1

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 01:01:29