React中useRef存储嵌套Map时修改useState状态导致ref同步变更问题
问题根源
- 你遇到的问题本质是JavaScript的浅拷贝特性导致的引用共享:
new Map(原有Map)仅能实现外层Map的浅拷贝,内层存储的Map属于引用类型,拷贝后的外层Map和原外层Map会共享同一个内层Map实例- 你的代码存在两处引用共享问题:
- 初始化阶段直接将同一个外层Map实例同时赋值给
oldState.current和weightsValues状态,二者从根节点开始就是同一个引用 onChange方法中仅拷贝了外层Map,修改内层Map时直接操作了和oldState共享的实例,自然会导致二者同步变更
- 初始化阶段直接将同一个外层Map实例同时赋值给
修复方案
首先实现双层Map的专属深拷贝工具方法,不需要引入通用深拷贝逻辑,性能更优:
// 双层嵌套Map深拷贝函数 function deepCloneNestedMap(originalMap) { const clonedOuterMap = new Map() for (const [outerKey, innerMap] of originalMap) { clonedOuterMap.set(outerKey, new Map(innerMap)) } return clonedOuterMap }
1. 修改初始化逻辑
给oldState存储独立的深拷贝副本,避免和状态共享引用:
useEffect(()=>{ const weightsAndClassesTemp=new Map(); weightsAndClassesTemp.set("A",new Map()) weightsAndClassesTemp.set("B",new Map()) weightsAndClassesTemp.get("A").set("aa",0.65) weightsAndClassesTemp.get("A").set("bb","c") weightsAndClassesTemp.get("B").set("aa",0.9) weightsAndClassesTemp.get("B").set("bb","a") let response={data:{valueOfWeightAndClass:weightsAndClassesTemp}} // 存储深拷贝后的独立副本 oldState.current = deepCloneNestedMap(response.data.valueOfWeightAndClass) updateWeightsValues(response.data.valueOfWeightAndClass) },[])
2. 修改值变更逻辑
修改内层Map前先做独立拷贝,避免修改原引用:
function onChange(value,className,weight){ // 拷贝外层Map const newClassWeights = new Map(weightsValues) // 拷贝目标内层Map后再修改 const targetInnerMap = new Map(newClassWeights.get(className)) targetInnerMap.set(weight, value) // 将新的内层Map替换回外层结构 newClassWeights.set(className, targetInnerMap) updateWeightsValues(newClassWeights) }
3. 回退逻辑示例
需要回退时同样做深拷贝,避免后续状态修改影响历史快照:
function rollbackToOldState() { updateWeightsValues(deepCloneNestedMap(oldState.current)) }
内容的提问来源于stack exchange,提问作者Ron Tyntarev
相关产品推荐
相关产品推荐

