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

React嵌套循环渲染state时状态更新后展示数据未同步刷新

问题产生原因

这是React状态更新时违反不可变原则导致的典型问题,核心逻辑如下:

  • React触发组件重渲染的判断依据是状态的引用地址是否发生变化,做浅对比时如果发现传入的状态和原状态引用相同,就会判定状态无更新,跳过重渲染流程。
  • 你的代码中const updatedFormData = formData只是做了引用赋值,没有创建新的状态对象,后续遍历执行cat.rows.push()是直接修改原状态内部的数组,属于可变修改(mutation)。最后调用setFormData传入的还是原状态的引用地址,React不会触发重渲染,就出现了状态值已变化但页面不刷新的现象。
  • 额外的代码笔误:渲染逻辑中c.rows.map((row) => (...))定义的遍历参数是row,但输入框绑定值时用的是field.information1、field.information2,变量名不匹配也会导致渲染报错。
修复方法

修复核心是全程遵循状态不可变原则,不要直接修改原状态,而是通过展开运算符创建对象、数组的新副本,在副本上做修改后再传入状态更新函数。

修正后的新增行逻辑

function addRow(category) {
  const updatedFormData = {
    ...formData,
    categories: formData.categories.map(cat => {
      if (cat.name === category) {
        // 匹配到目标分类时,返回新的分类对象,rows创建新数组追加内容
        return {
          ...cat,
          rows: [
            ...cat.rows,
            {
              information1: "test",
              information2: "this is a test"
            }
          ]
        }
      }
      // 非目标分类直接返回原对象即可
      return cat
    })
  }
  setFormData(updatedFormData)
}

修正后的渲染逻辑

补全变量名匹配,同时给列表项加上唯一key属性,符合React渲染要求:

{formData?.categories?.map(c => (
  <div key={c.name}>
    {c.name}
    {c.rows.map((row, rowIndex) => (
      <div key={rowIndex}>
        <input value={row.information1} />
        <textarea value={row.information2}></textarea>
        <button onClick={() => addRow(c.name)}>Add Row here</button>
      </div>
    ))}
  </div>
))}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:09:17