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
相关产品推荐
相关产品推荐

