使用Apollo Client刷新JWT Token后,如何重新渲染组件?
问题原因
你的errorLink逻辑存在两个关键问题,导致组件无法感知新请求的成功响应:
- 处理token过期时,没有将重新发送请求的结果返回给Apollo请求链路,Apollo Client无法更新组件状态,会一直停留在错误状态。
- 嵌套Promise的写法导致链路无法正确接收新请求的Observable,异步逻辑衔接断裂。
修复方案
修改errorLink,确保刷新token并重新发送请求后,将新请求的Observable返回给链路,替换原错误结果。同时简化异步逻辑,避免嵌套Promise:
const errorLink = onError(({ graphQLErrors, operation, forward }) => { if (graphQLErrors) { // 提取公共的token刷新+重新请求逻辑 const handleTokenRefresh = async () => { try { // 执行刷新token操作 await Refreshtoken(); // 获取新的access token const newToken = await getNewToken("access-token"); // 更新当前请求的header(保留原有header字段) operation.setContext((prevContext) => ({ headers: { ...prevContext.headers, authorization: `Bearer ${newToken}`, }, })); // 重新发送请求并返回结果 return forward(operation); } catch (e) { console.log("Token刷新失败", e); // 刷新失败可抛出错误或跳转登录页 throw e; } }; for (const err of graphQLErrors) { console.log(`[GraphQL error]: Message: ${err.message}, Location: ${err.locations}, Path: ${err.path}`); // 统一处理两种需要刷新token的错误 if (err.message === "jwt expired" || err.message === "Access denied! You don't have permission for this action!") { // 返回包装后的Observable,让链路接收新请求的结果 return fromPromise(handleTokenRefresh()).flatMap((result) => result); } } } if (networkError) { console.log(`[Network error]: ${networkError}`); } });
关键改动说明
- 提取公共逻辑:将token刷新、请求头更新、重新请求的逻辑封装成async函数,避免重复代码。
- 返回Observable:用
fromPromise将异步操作包装成Observable,通过flatMap转发重新请求的结果,确保Apollo链路能接收到新响应。 - 正确更新请求头:使用函数式写法更新context,保留原有header的其他字段,只覆盖authorization。
- 终止错误遍历:匹配到目标错误时直接返回新Observable,避免继续处理其他错误。
组件端注意事项
你的useQuery配置fetchPolicy: 'no-cache'是合理的,确保不会读取旧缓存。若组件仍未更新,检查:
- 刷新token后是否正确将新token存入
getNewToken可读取的位置(如cookie/localStorage)。 - 重新发送的请求是否在Network标签中返回了正确数据。
内容的提问来源于stack exchange,提问作者Kiria
相关产品推荐
相关产品推荐

