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

React同一事件回调内调用setState后useState状态未更新问题

问题原因

React函数组件里useState触发的状态更新是异步批处理的,同一段同步执行的事件回调中,调用状态更新方法后,当前函数闭包里捕获的状态常量不会同步变更,必须等当前同步逻辑全部执行完成、组件完成重渲染后,新的状态值才会在下次渲染生成的函数作用域中生效。
你在同一个onClick回调里调用setUsers后立刻遍历users,拿到的永远是当前渲染周期绑定的旧状态值,这是Hooks的闭包特性导致的正常表现,不是框架bug。

修复方案

你不需要等状态更新完成再做统计,filter生成的afterFilter本身就是删除操作完成后的最新航班数据,直接基于这个值做统计即可,完全不需要等待状态生效。
修正后的代码如下:

const [users, setUsers] = useState([]);

// 调整deleteFlight,返回过滤后的最新数组
const deleteFlight = (num) => {
  const afterFilter = users.filter((user) => user.numFlight !== num);
  setUsers(afterFilter);
  return afterFilter;
};

<button
  onClick={() => {
    const inp = numFlightInp.current.value;
    const targetFlightNum = Number(inp);

    // 先做存在性校验,避免无意义的状态更新
    if (!checkDuplicateFlight(targetFlightNum)) {
      alert("not found match");
      return;
    }

    // 执行删除,拿到最新的航班列表
    const latestUserList = deleteFlight(targetFlightNum);
    alert("deleted");

    // 直接基于最新列表统计数据
    let passengerCnt = 0;
    let totalFlightCnt = 0;
    latestUserList.forEach((user) => {
      passengerCnt += user.passenger;
      totalFlightCnt++;
    });

    setFlightCnt2(totalFlightCnt);
    setPassengerCnt2(passengerCnt);
  }}
>
  delete
</button>

额外说明

  • 你原有代码的执行顺序有问题:先执行删除操作再做航班存在性校验,会导致输入不存在的航班号时,也会触发一次无意义的setUsers调用和组件重渲染,把校验逻辑前置性能更好。
  • 这类场景不需要用useEffect监听users变化再做统计,会多绕一层渲染逻辑,属于不必要的复杂度。
  • 不要用Ref强行存储最新状态来绕开闭包,属于过度设计,你在调用setUsers之前就已经拿到了最新的数据集,直接复用即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 10:15:34