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

React使用useState重置major、minor状态后赋值失效问题求助

问题根因

  • useState 的更新是异步批量的,你在 handleSelectInput 里调用 setMajor(majorStates) 和 setMinor([]) 后,当前函数作用域内的 major、minor 变量还是闭包捕获的旧值,不会立刻变成重置后的值,后续你操作的依然是旧数据,所以重置逻辑看似没生效。
  • 你直接修改了 major 数组里的原有对象,属于直接变更state的引用类型值,违反React状态不可变的更新原则,会导致状态更新异常、渲染触发异常。
  • 你在循环里反复调用 setMajor、setMinor,而且每次更新都用了闭包内的旧状态值,所以minor会出现累加问题,因为每次 setMinor([...minor, res.data[i]]) 里的 minor 都是请求发起时的旧值,不是上一轮循环更新后的值。

修正方案

你可以先基于初始的majorStates构造新的major数组,先把接口返回的数据处理完,再一次性更新状态,不要直接修改原有state、不要在循环里反复更新状态。

// 初始状态定义保持不变,单独抽离的初始常量不要直接修改
const majorStates = new Array(10).fill(null).map((_, idx) => ({
  tank: idx + 1,
  material: '',
  required: 0,
  actual: 0,
  difference: 0,
  crit: 0,
  percent: 0,
}))
const [major, setMajor] = useState(majorStates)
const [minor, setMinor] = useState([])

const handleSelectInput = async (e) => {
  const { value } = e.target
  try {
    const res = await axios.put(`${PATH}/main-start`, { product: value })
    // 深拷贝初始值构造新的major数组,避免修改到初始常量和原有state
    const newMajor = JSON.parse(JSON.stringify(majorStates))
    const newMinor = []
    // 先遍历处理所有接口返回数据
    res.data.forEach(item => {
      const requiredWt = parseFloat(item.required_wt)
      if (item.type === 'MAJOR') {
        // 找到对应tank的索引,修改新数组里的对象
        const tankIdx = newMajor.findIndex(tk => tk.tank === item.tank)
        if (tankIdx > -1) {
          newMajor[tankIdx].material = item.material
          newMajor[tankIdx].required = requiredWt
        }
      } else {
        newMinor.push({
          ...item,
          required_wt: requiredWt
        })
      }
    })
    // 所有数据处理完成后一次性更新状态
    setMajor(newMajor)
    setMinor(newMinor)
  } catch (err) {
    console.log(err)
  }
}

如果接口返回的major数据的tank编号和数组下标是一一对应的(比如tank:1对应下标0),可以直接用下标定位,不用findIndex,性能更好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 14:51:02