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

Next.js中Apollo Client获取Cookie返回undefined问题求助

问题场景

在Next.js客户端组件中使用js-cookie库调用Cookies.get("accessToken")时,始终返回undefined或空字符串,相关代码如下:

"use client";

import React from "react";
import {
  ApolloClient,
  InMemoryCache,
  ApolloProvider,
  ApolloLink,
  HttpLink,
} from "@apollo/client";
import { SSRMultipartLink } from "@apollo/experimental-nextjs-app-support";
import { setContext } from "@apollo/client/link/context";
import Cookies from "js-cookie";

export default function ApolloProviderClient({
  children,
}: React.PropsWithChildren) {
  const httpLink = new HttpLink({
    uri: "http://localhost:4000/",
  });

  // Middleware to add Authorization header dynamically
  const authLink = setContext((_, { headers }) => {
    const accessToken = Cookies.get("accessToken");
    // DEBUGGING: Log all cookies
    console.log(accessToken);

    return {
      headers: {
        ...headers,
        Authorization: accessToken ? `Bearer ${accessToken}` : "",
      },
    };
  });

  const client = new ApolloClient({
    cache: new InMemoryCache(),
    link:
      typeof window === "undefined"
        ? ApolloLink.from([
            // in a SSR environment, if you use multipart features like
            // @defer, you need to decide how to handle these.
            // This strips all interfaces with a `@defer` directive from your queries.
            new SSRMultipartLink({
              stripDefer: true,
            }),
            authLink.concat(httpLink),
          ])
        : authLink.concat(httpLink),
    credentials: "include",
  });

  return <ApolloProvider client={client}>{children}</ApolloProvider>;
}

针对上述场景,有三个技术问题需要解答:

  1. 为何Cookies.get()会返回undefined或空字符串?
  2. 使用js-cookie时存在哪些常见误区或错误操作?
  3. React客户端组件中是否有更优的Cookie获取方式?

问题解答

1. 为何Cookies.get()返回undefined或空字符串?

  • Cookie带HttpOnly属性:如果后端设置accessToken时添加了HttpOnly标记,浏览器会禁止前端JS(包括js-cookie)读取该Cookie,这是防XSS的安全机制。
  • 域名/路径不匹配:后端设置Cookie时指定的域名(如localhost:4000)或路径(如/api)与前端页面的域名/路径不一致,导致前端无法访问该Cookie。
  • Cookie未设置或已过期:检查浏览器开发者工具的Application > Cookies面板,确认accessToken是否存在、是否未过期。
  • 名称大小写不匹配:Cookie名称区分大小写,若后端设置的是AccessToken,用accessToken读取会返回undefined。
  • SSR阶段误执行:虽然代码判断了window,但ApolloClient初始化时,authLink可能在客户端hydration前的阶段触发,此时Cookie可能未被正确读取(这种情况概率较低)。

2. 使用js-cookie的常见误区

  • 读取HttpOnly Cookie:js-cookie只能读取无HttpOnly属性的Cookie,这是高频错误。
  • 忽略SameSite属性:若Cookie设置SameSite=Strict/Lax,跨域场景下可能无法携带,导致前端读取不到。
  • 域名/路径设置错误:设置Cookie时未指定与前端匹配的域名或路径,导致Cookie无法被当前页面访问。
  • 非浏览器环境调用:在Node.js(SSR/SSG)中直接调用Cookies.get(),因无document对象返回undefined,必须先判断window存在。
  • 编码解码不一致:后端设置Cookie时编码了值,前端未解码,会得到空或乱码;反之亦然。

3. React客户端组件更优的Cookie获取方式

  • 原生document.cookie解析:无需依赖库,手动解析字符串获取指定Cookie:
    const getCookie = (name: string): string | undefined => {
      const value = `; ${document.cookie}`;
      const parts = value.split(`; ${name}=`);
      if (parts.length === 2) return parts.pop()?.split(';').shift();
      return undefined;
    };
    
    // 使用示例
    const accessToken = getCookie('accessToken');
    
  • react-cookie库:提供React Hooks API,支持监听Cookie变化,更贴合React组件逻辑:
    import { useCookies } from 'react-cookie';
    
    // 在组件内使用
    const [cookies] = useCookies(['accessToken']);
    const accessToken = cookies.accessToken;
    
  • Apollo客户端专属优化:在authLink中直接用原生方式读取,避免额外依赖,确保仅在浏览器环境执行:
    const authLink = setContext((_, { headers }) => {
      let accessToken = '';
      if (typeof window !== 'undefined') {
        accessToken = getCookie('accessToken') || '';
      }
      return {
        headers: {
          ...headers,
          Authorization: accessToken ? `Bearer ${accessToken}` : '',
        },
      };
    });
    
  • 服务器组件传递Cookie:若accessToken是HttpOnly的,前端无法直接读取,可在服务器组件用Next.js的cookies()钩子获取后,通过props传递给客户端组件(注意敏感信息的安全性)。

内容的提问来源于stack exchange,提问作者Fikri Lazuardi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 08:28:15