React Props派生State不更新 编辑丢弃修改回退失效排查
问题根因
状态不回退的核心原因是浅拷贝导致的引用共享+直接修改状态对象,和editMode切换逻辑本身无关:
- 初始化
originalValues和modifiedValues时用的{ ...propsData }属于浅拷贝,仅会复制最外层对象的属性,内层的schools数组、数组内的学校对象、licensedproducts授权数组,在两个state和原props之间都是共享同一块内存引用的 - 复选框变更逻辑里直接修改了
currentValue.schools[currentIndex].licensedproducts,属于直接修改原状态对象的违规操作,因为引用共享,修改modifiedValues的同时originalValues里的对应数据也被同步篡改了,切回非编辑模式读取originalValues时,拿到的本身就是被修改过的值,自然无法回退 - 点击丢弃按钮时没有重置modifiedValues,下次进入编辑模式会残留上次未保存的修改
修复方案
1. 所有状态拷贝使用深拷贝,切断引用关联
放弃浅拷贝写法,用内置的structuredClone方法做深拷贝,保证originalValues和modifiedValues是完全独立的两个对象,不存在共享引用。如果需要兼容极老版本浏览器,可以替换为JSON.parse(JSON.stringify(数据))实现深拷贝。
2. 退出编辑模式时重置修改状态
点击丢弃按钮退出编辑时,主动把modifiedValues重置为原始值的深拷贝,清空未保存的修改。
3. 修正状态更新逻辑,禁止直接修改原状态对象
更新modifiedValues时,先基于当前值生成独立的深拷贝对象,再对新对象做修改后返回,不要直接在原状态对象上改属性。
修复后的关键代码
// 初始化状态时改用深拷贝 const [originalValues, setOriginalValues] = useState(structuredClone(propsData)); const [modifiedValues, setModifiedValues] = useState(structuredClone(propsData)); useEffect(() => { setOriginalValues(structuredClone(propsData)); setModifiedValues(structuredClone(propsData)); }, [propsData]); // 切换编辑状态时,退出模式下重置修改值 const toggleEdit = () => { setEditMode((current) => { if (current) { setModifiedValues(structuredClone(originalValues)); } return !current; }); }; // 保存时做深拷贝,避免后续修改影响已存的原始值 const saveButton = () => { setOriginalValues(structuredClone(modifiedValues)); }; // 复选框变更逻辑,先拷贝再修改 onChange={() => setModifiedValues((currentValue) => { const newVal = structuredClone(currentValue); if (isEnabled) { newVal.schools[currentIndex].licensedproducts = newVal.schools[currentIndex].licensedproducts.filter((value) => value !== thisBundle.id); } else { newVal.schools[currentIndex].licensedproducts.push(thisBundle.id); } return newVal; }) }
内容的提问来源于stack exchange,提问作者LuisEnMarroquin
相关产品推荐
相关产品推荐

