React Query 取消pending或之前发起的未完成请求失败如何解决?
React Query 未触发请求取消的解决方案
你的实现核心问题是在await axios.get执行完成后才给响应对象挂载cancel方法,此时请求已经结束,React Query无法在请求pending阶段获取到取消方法,因此无法触发取消操作。
推荐实现方式(适配React Query v3+ + Axios 0.22+)
React Query的查询函数默认会传入包含signal属性的上下文对象,直接配合Axios原生支持的AbortSignal使用即可,不需要手动维护CancelToken:
const [value, setValue] = React.useState<boolean>(false); const getData = async (value: number, signal: AbortSignal): Promise<any> => { return axios.get(`https://xxxxxx?value=${value}`, { signal, }).then(res => res.data); } const { data: result, status, error, isFetching } = useQuery( ['getData', value], // 从查询函数上下文拿到signal传给请求方法 (context) => getData(value, context.signal), { refetchOnWindowFocus: false, } );
该实现可自动覆盖所有取消场景:
- 当
value变化触发查询key变更时,旧的pending请求会被自动取消 - 当组件卸载时,关联的pending请求会被自动取消
- 如需手动批量取消请求,可通过
useQueryClient获取实例后调用queryClient.cancelQueries({ queryKey: ['getData'] })
兼容旧版Axios(必须使用CancelToken的场景)
如果你的Axios版本低于0.22不支持AbortSignal,需要给返回的Promise对象挂载cancel方法,而不是给await后的响应对象挂载:
const getData = (value: number): Promise<any> => { const CancelToken = axios.CancelToken const source = CancelToken.source() // 不要加await,直接返回未resolve的Promise实例 const promise = axios.get(`https://xxxxxx?value=${value}`, { cancelToken: source.token, }).then(res => res.data); // 给Promise实例挂载cancel方法供React Query调用 (promise as any).cancel = () => { source.cancel('Query was cancelled by React Query') } return promise; }
内容的提问来源于stack exchange,提问作者Sole
相关产品推荐
相关产品推荐

