如何在JavaScript中更新数组内特定对象的属性值
问题根因
- 状态数组引用未发生变化:你直接将原状态数组
localPreRoutingCall赋值给localArray,二者指向同一个内存地址,调用splice修改数组后引用没有变更,React浅比较判定状态未更新,不会触发组件重渲染。 - 循环渲染未添加唯一key:map遍历渲染元素时没有给外层包裹元素添加
key属性,可能导致React Diff算法无法正确识别需要更新的节点。 - 冗余的
e.persist():React17及之后版本已经移除了合成事件池机制,该调用已经没有实际作用。
修复方案
1. 修正状态更新函数
修改changeObjectValue,遵循React不可变更新原则,先拷贝原数组生成新的数组实例,再修改新数组后更新状态,推荐用更简洁的map方式实现:
const changeObjectValue = (value, targetItem) => { setLocalPreRoutingCall(prev => prev.map(item => { return item.id === targetItem.id ? {...item, value} : item })) };
如果要保留原有的lodash查找逻辑,也可以修改为:
const changeObjectValue = (value, item) => { console.log("@@ array", value); // 浅拷贝原数组生成新实例 let localArray = [...localPreRoutingCall]; const index = _.findIndex(localArray, { id: item.id }); if (index !== -1) { localArray[index] = { ...item, value: value }; setLocalPreRoutingCall(localArray); } };
2. 给循环渲染项添加唯一key
修改map渲染部分,给外层的Fragment添加唯一key属性:
localPreRoutingCall && localPreRoutingCall.map((item, index) => ( // 优先用item.id作为key,仅当数组不会发生增删、排序操作时可临时用index替代 <React.Fragment key={item.id}> <div className="pre-route-title">{item?.field_title}</div> <textarea placeholder="Enter something" className="pre-route-textarea" value={item?.value} onChange={(e) => { changeObjectValue(e.target.value, item); }} /> <div className="pre-route-description"> {item?.description} </div> </React.Fragment> ))
内容的提问来源于stack exchange,提问作者Jonas
相关产品推荐
相关产品推荐

