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

React-query抛出Error时onError回调未执行问题求助

问题分析与解决方案

你的问题核心在于:useQuery没有捕获到fetchPost抛出的错误,导致onError回调未触发、isError始终为false。结合你的代码,主要有以下几个可能的原因和对应的修复方案:

1. fetchPost中错误包装的冗余与问题

你在fetchPost中用try/catch捕获Axios错误后,手动抛出了一个新的Error对象:

catch (error: any) {
  throw new Error(error);
}

这种包装会把Axios返回的AxiosError对象转换成普通Error,错误信息会变成[object Object](直接把对象传给Error构造函数导致)。更关键的是,react-query期望接收原始请求错误对象,这种不必要的包装可能打乱错误处理流程。

修复方案

去掉fetchPost中的try/catch,让错误直接传递给useQuery:

export const fetchPost = async (webId: string) => {
  const response = await axiosInstance.get(`${API_URL}/post/${webId}`);
  return response.data;
};

异步函数会自动将内部抛出的错误转换为rejected Promise,useQuery会正确捕获这个状态并触发onError回调。

2. Axios拦截器的错误处理逻辑漏洞

你的响应拦截器存在两个潜在问题:

  • 未检查originalRequest是否存在:当请求未成功发送(如网络错误)时,error.config会是undefined,访问originalRequest._retry会抛出额外错误,干扰主错误流程。
  • refreshAccessToken()未添加错误捕获:如果刷新token失败,会导致拦截器函数抛出未处理错误,可能绕过useQuery的错误处理。

修复方案

优化拦截器的错误处理逻辑:

axiosInstance.interceptors.response.use(
  (response: AxiosResponse) => {
    const accessToken = response.headers[ACCESS_TOKEN_HEADER];
    const refreshToken = response.headers[REFRESH_TOKEN_HEADER];

    if (accessToken && refreshToken) {
      localStorage.setItem(ACCESS_TOKEN_HEADER, accessToken);
      localStorage.setItem(REFRESH_TOKEN_HEADER, refreshToken);
    }

    return response;
  },
  async (error: AxiosError) => {
    const originalRequest = error.config;
    const errorHeader = error.response?.headers.error;

    // 确保originalRequest存在再处理重试逻辑
    if (originalRequest && errorHeader === EXPIRED_ACCESS_TOKEN_ERROR && !originalRequest._retry) {
      originalRequest._retry = true;
      try {
        await refreshAccessToken();
        return axiosInstance(originalRequest);
      } catch (refreshErr) {
        // 刷新token失败时,直接拒绝原请求
        return Promise.reject(refreshErr);
      }
    } else if (errorHeader === EXPIRED_REFRESH_TOKEN_ERROR) {
      // 清理过期的token
      localStorage.removeItem(ACCESS_TOKEN_HEADER);
      localStorage.removeItem(REFRESH_TOKEN_HEADER);
    }

    return Promise.reject(error);
  },
);

3. 额外排查点

  • 检查useQuery的enabled配置:如果无意中设置了enabled: false,useQuery不会执行请求,自然不会触发错误回调。
  • 确认params!.postId的有效性:如果params是undefined,params!.postId会抛出TypeError,这个错误发生在fetchPost调用之前,需确保params在组件渲染时已存在(可通过可选链params?.postId或条件渲染避免)。
  • 升级react-query版本:旧版本的react-query可能存在异步函数错误处理的bug,建议升级到最新的@tanstack/react-query。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 07:57:12