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

登出时无法清除apollo-client缓存,新用户登录后仍展示旧用户数据

问题根因

  1. Apollo Client 实例化时硬编码了请求头的 Authorization 字段,该值仅会在实例创建时读取一次 localStorage,后续切换用户更新 localStorage 中的 token 后,请求仍然携带旧用户的 token,后端返回的旧用户数据会覆盖你手动写入缓存的新用户信息。
  2. 登出逻辑顺序错误,先清理缓存再清除本地身份凭证,清理缓存时触发的活跃查询自动重发仍然携带旧 token,拉取到旧用户数据。
  3. 冗余的缓存清理操作互相冲突:clearStore 和 resetStore 功能重叠,重复调用会导致预期外的缓存行为。

解决方案

1. 修正 Apollo Client 配置,使用动态请求头

移除硬编码的 headers 配置,改用 setContext 中间件在每次请求前读取最新的 token:

import { setContext } from '@apollo/client/link/context';
import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client';

const httpLink = createHttpLink({
  uri: config.apiUrl,
});

// 每次请求前动态注入最新的授权头
const authLink = setContext((_, { headers }) => {
  const token = localStorage.getItem(config.localStorage);
  return {
    headers: {
      ...headers,
      Authorization: token ? `Bearer ${token}` : '',
    }
  }
});

const apolloClient = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache({
    // 如果你的用户表主键不是默认的`id`,需在此处指定主键字段,避免缓存把不同用户识别为同一对象
    typePolicies: {
      User: {
        keyFields: ['userId'] // 替换为你实际的用户主键字段名
      }
    }
  }),
});

2. 修正登出逻辑,调整操作顺序

移除冗余的缓存清理调用,先清除本地身份凭证再清理缓存:

onClick={() => {
  // 第一步:先清除本地存储的token和全局用户状态
  localStorage.removeItem(config.localStorage);
  dispatch(logoutUser);
  // 第二步:重置缓存,自动重发所有活跃查询(此时已无有效token,不会返回旧用户数据)
  client.resetStore()
    .then(() => history.push('/'));
}}

3. 简化登录逻辑,无需手动写入缓存

登录成功后先存储新用户的 token,再重置缓存即可,useUserQuery 会自动携带新 token 请求最新的用户数据,无需手动调用 writeQuery:

sendLogin({
  variables: login,
  onCompleted: (data) => {
    // 存储新用户的token
    localStorage.setItem(config.localStorage, data.login.token);
    // 重置缓存后活跃查询会自动拉取新用户数据
    client.resetStore();
    history.push('/');
  }
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 06:18:03