React中按钮触发Axios请求时,组件卸载如何取消请求?
处理按钮触发请求的组件卸载取消逻辑
对于按钮点击触发的请求,核心思路是把AbortController实例通过useRef跨渲染周期保存,这样组件卸载时能拿到实例并取消请求,同时还能处理重复点击的情况(避免多个请求并行)。
完整代码示例
import { useRef, useEffect, useState } from 'react'; import axiosPrivate from './your-axios-instance'; function UserProfile() { const abortControllerRef = useRef(null); const [profileInformation, setProfileInformation] = useState(null); // 组件卸载时自动取消未完成的请求 useEffect(() => { return () => { abortControllerRef.current?.abort(); }; }, []); const handleFetchProfile = async () => { // 取消之前未完成的请求(可选但实用,防止重复点击导致多请求) if (abortControllerRef.current) { abortControllerRef.current.abort(); } // 创建新的AbortController并保存到ref const controller = new AbortController(); abortControllerRef.current = controller; try { const response = await axiosPrivate.get('/user/information', { signal: controller.signal, }); setProfileInformation(response.data.user); } catch (err) { // 忽略AbortError(这是主动取消请求导致的,不属于业务错误) if (err.name !== 'AbortError') { console.error('请求失败:', err); } } finally { // 请求完成后清空ref,避免卸载时重复执行abort abortControllerRef.current = null; } }; return ( <div> <button onClick={handleFetchProfile}>加载用户信息</button> {profileInformation && ( <div className="profile"> <h3>{profileInformation.name}</h3> <p>{profileInformation.email}</p> </div> )} </div> ); }
关键细节说明
- 用useRef存控制器:useRef的特性是跨渲染周期保存引用,且修改不会触发组件重渲染,非常适合存储这类临时实例。
- 组件卸载时清理:通过useEffect的清理函数,在组件卸载时检查ref中是否有未完成的请求控制器,调用
abort()阻止后续的state更新。 - 处理重复点击:每次发起新请求前,先取消之前可能还在pending的请求,避免接口返回顺序混乱或资源浪费。
- 区分AbortError:主动取消请求会抛出
AbortError,这类错误不需要作为业务异常处理,所以在catch里做过滤。
内容的提问来源于stack exchange,提问作者burki
相关产品推荐
相关产品推荐

