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

React中useRef存储嵌套Map时修改useState状态导致ref同步变更问题

问题根源

  • 你遇到的问题本质是JavaScript的浅拷贝特性导致的引用共享:
    • new Map(原有Map) 仅能实现外层Map的浅拷贝,内层存储的Map属于引用类型,拷贝后的外层Map和原外层Map会共享同一个内层Map实例
    • 你的代码存在两处引用共享问题:
      1. 初始化阶段直接将同一个外层Map实例同时赋值给oldState.current和weightsValues状态,二者从根节点开始就是同一个引用
      2. onChange方法中仅拷贝了外层Map,修改内层Map时直接操作了和oldState共享的实例,自然会导致二者同步变更

修复方案

首先实现双层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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 10:06:03