在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
相关产品推荐
相关产品推荐

