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

在TanStack Query中根据网络状态取消查询失败,如何解决?

在React TanStack Query中离线时取消查询的解决方案

问题分析

你当前的实现存在两个核心问题:

  • 手动维护axios.CancelToken容易出现引用不一致:每次queryFn执行都会新建CancelToken,当离线触发取消时,可能操作的是旧的Token实例,导致请求未被正确取消。
  • Axios取消请求会抛出CancelError,TanStack Query默认将其判定为查询错误(触发isError),而非取消状态,导致你看到错误提示而非预期的离线数据展示。

修复步骤

1. 改用TanStack Query内置的AbortSignal替代Axios CancelToken

TanStack Query v4原生支持AbortController,无需手动维护CancelToken,直接使用queryFn参数中的signal即可实现请求取消,同时避免引用不一致问题。

修改查询逻辑:

import { useQuery, useQueryClient } from '@tanstack/react-query';
import axios, { CancelError } from 'axios';

export default function Body({ searchText, id, alvoId }: BodyProps) {
  const { isOnline } = useOnlineStatus();
  const queryClient = useQueryClient();

  const { data, isError, isLoading, refetch, error } = useQuery({
    queryKey: [`dsc/${id}`],
    queryFn: async ({ signal }) => {
      // 使用Query提供的AbortSignal,无需手动创建CancelToken
      const response = await actionsGet(id, signal);
      return response;
    },
    // 取消错误不触发重试
    retry: (failureCount, err) => {
      return !(err instanceof CancelError || err.name === 'AbortError');
    },
    // 仅处理非取消类错误的提示
    onError: (err) => {
      if (isOnline && !(err instanceof CancelError || err.name === 'AbortError')) {
        showToast('customToast', 'Error', 'Verifique a conexão com a internet', 'error');
      }
    },
  });

  useEffect(() => {
    if (!isOnline) {
      // 调用Query内置方法取消目标查询
      queryClient.cancelQueries({ queryKey: [`dsc/${id}`] });
      // 加载离线数据
      if (!data) {
        handleDownloadedDisciplina();
      } else {
        setDisciplina(data?.content || []);
        handleDownloadedIds();
      }
    } else {
      // 在线时同步最新数据
      if (data) {
        setDisciplina(data?.content || []);
        handleDownloadedIds();
      } else {
        refetch();
      }
    }
  }, [data, isOnline, id, queryClient]);

  // ...其他组件逻辑
}

2. 更新请求函数以支持AbortSignal

修改actionsGet,将参数从cancelToken改为标准的AbortSignal(Axios原生支持该参数):

export async function actionsGet(
  id: string,
  signal?: AbortSignal
): Promise<any> {
  const response = await api.get(`/data/${id}`, {
    headers: {
      modulo: 'STUFF',
    },
    signal: signal,
  });

  return response.data;
}

3. 移除冗余的CancelToken维护

删除原来的cancelToken ref变量,因为现在Query会自动管理请求的取消信号,无需手动维护。

关键说明

  • 使用queryClient.cancelQueries可以精准取消指定queryKey的查询,确保操作的是当前活跃的请求。
  • 通过retry配置过滤取消错误,避免Query对取消请求进行重试。
  • 在onError中判断错误类型,仅对非取消类错误展示提示,避免离线时触发错误弹窗。

内容的提问来源于stack exchange,提问作者Nilton Schumacher F

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 07:35:20