Apollo GraphQL:重试失败查询后useQuery数据未更新问题
解决方案
1. 重试时更新当前操作的请求头
刷新令牌后,必须将新的accessToken更新到当前重试操作的请求头中,否则重试请求可能仍使用过期令牌(仅保存token但未同步到当前operation的headers)。修改onError链路实现:
import { setContext } from '@apollo/client/link/context'; // 定义authLink用于统一设置请求头 const authLink = setContext((_, { headers }) => { const token = getAccessToken(); // 从本地存储获取最新令牌 return { headers: { ...headers, authorization: token ? `Bearer ${token}` : '', } }; }); // 修正后的errorLink const errorLink = onError(({ networkError, operation, forward }) => { if (networkError && networkError.statusCode === 401) { return fromPromise( refreshtoken() .then(response => { saveAccessToken(response.accessToken); return response.accessToken; }) .catch(() => { // 刷新失败时处理退出登录等逻辑 logout(); return null; }) ).flatMap(newToken => { if (!newToken) return forward(operation); // 更新当前操作的请求头为新令牌 operation.setContext(({ headers = {} }) => ({ headers: { ...headers, authorization: `Bearer ${newToken}`, }, })); return forward(operation); }); } }); // 注意链路顺序:authLink -> errorLink -> httpLink const link = from([authLink, errorLink, httpLink]);
2. 调整fetchPolicy并确认缓存更新
你使用的cache-and-network策略会优先返回缓存数据再请求网络,若首次失败后缓存无数据,重试成功后需要确保结果正确写入缓存。可以临时切换为network-only测试,或者确认Apollo Client的缓存更新逻辑正常。
3. 手动触发查询刷新(兜底方案)
如果上述方法无效,可在重试成功后通过client.refetchQueries手动触发目标查询的重新获取:
const errorLink = onError(({ networkError, operation, forward, client }) => { if (networkError && networkError.statusCode === 401) { return fromPromise(refreshtoken()).flatMap(response => { saveAccessToken(response.accessToken); // 重试请求完成后,手动刷新当前查询 return forward(operation).tap(() => { client.refetchQueries({ include: [operation.operationName], }); }); }); } });
4. 升级Apollo Client版本
你使用的3.6.6版本存在部分关于错误链路重试后状态不更新的已知问题,升级到3.7.x及以上版本可修复此类问题。
内容的提问来源于stack exchange,提问作者Bruna Silva
相关产品推荐
相关产品推荐

