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

React中useEffect结合AbortController状态更新异常问题

问题根源与解决方案

问题原因

你遇到的情况本质是:旧请求的响应可能在新请求完成后才返回,或者AbortController没能拦截到已经完成的请求(比如服务器响应过快,请求已经结束才触发abort),这时候旧请求的setData会覆盖新请求的状态。而你添加的setData('')只是重置了当前状态,但无法阻止后续旧请求的状态更新。

解决思路

除了用AbortController取消未完成的请求,还需要在更新状态前校验当前组件的logID是否和发起请求时的一致,确保只有对应请求的结果才会更新状态。

修改后的代码

useEffect(() => {
  const controller = new AbortController();
  const signal = controller.signal;
  // 记录发起请求时的logID
  const currentLogID = router.query.logID;

  const fetchData = async () => {
    try {
      setData('');

      const res = await axios.get(`/api/test?logID=${currentLogID}`, { signal });
      // 校验当前组件的logID是否和请求时一致,一致才更新状态
      if (router.query.logID === currentLogID) {
        setData(res.data);
      }
    } catch (error) {
      if (error.name !== 'AbortError') {
        console.error(error);
      }
    }
  };

  if (currentLogID) {
    fetchData();
  }

  return () => {
    controller.abort();
  };
}, [router.query.logID]); // 移除setData,因为useState返回的setter是稳定的,无需加入依赖

额外说明

  • 移除setData的依赖:React官方明确说明,useState返回的状态更新函数是稳定引用,不会在组件重新渲染时变化,所以不需要加入useEffect的依赖数组,避免不必要的useEffect触发。
  • 双重保险:AbortController负责拦截未完成的请求,logID校验负责过滤已完成但过时的请求结果,两者结合彻底解决状态被旧请求覆盖的问题。

内容的提问来源于stack exchange,提问作者Brandon Han

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 11:35:14