React中如何正确取消未完成的Ajax请求?

公孙万华 阅读 6

我在用useEffect做数据请求,切换页面时老报“Can’t perform a React state update on an unmounted component”错误。试过AbortController但好像没生效,是不是哪里写错了?

useEffect(() => {
  const controller = new AbortController();
  fetch('/api/data', { signal: controller.signal })
    .then(res => res.json())
    .then(data => setData(data));
  
  return () => controller.abort();
}, []);
我来解答 赞 2 收藏
二维码
手机扫码查看
1 条解答
书生シ振巧
你的代码思路是对的,但漏了一个关键点:AbortError 没处理。

fetch 被 abort 时会抛出一个 AbortError,这个错误会打断 .then 链,但如果你不 catch 它,默认行为有点坑。而且更重要的,即使请求被取消了,如果此时组件已经卸载,setData 还是会触发那个 unmounted 错误。

正确写法是这样的:

useEffect(() => {
let isMounted = true;
const controller = new AbortController();

fetch('/api/data', { signal: controller.signal })
.then(res => res.json())
.then(data => {
if (isMounted) {
setData(data);
}
})
.catch(err => {
if (err.name !== 'AbortError') {
console.error('请求失败:', err);
}
});

return () => {
isMounted = false;
controller.abort();
};
}, []);


两个要点:

一是加个 isMounted 标记,在 setData 前判断组件是否还挂着。controller.abort() 只能阻止请求发出去或者拿到响应,但已经拿到响应后还是会往下走 then,所以必须自己判断。

二是 catch 里要区分 AbortError 和其他错误。AbortError 是正常的取消行为,不需要抛出来,其他错误(比如网络断了一般还是得处理一下)。

复制过去试试,基本就解决了。
点赞
2026-03-13 19:10