【问题标题】:Update immutable js nested object with new value用新值更新不可变的 js 嵌套对象
【发布时间】:2021-09-18 21:16:23
【问题描述】:

我有 2 个不可变对象。结构如下图


    const state = fromJS({
       "a":"value1",
       "b":{
          "c":"value2"
       },
       "d":[ ],
       "e":{
          "f":"value3",
          "g":{
             "h":true
          }
       }
    })
    
    and
     
    const updateVal = fromJS({
    "b":{"c": "newValue"},
       "e": {"g":{"h": false"}}
    })

我想要的结果是


     state = fromJS({
       "a":"value1",
       "b":{
          "c":"newValue"
       },
       "d":[ ],
       "e":{
          "f":"value3",
          "g":{
             "h":false
          }
       }
    })

我尝试了 mergeWith、mergeDeep 但总是得到结果


    var state = fromJS({
           "a":"value1",
           "b":{
              "c":"newValue" // this is updating as I have same new object structure
           },
           "d":[ ],
           "e":{ // here I am loosing other values
              "g":{
                 "h":false
              }
           }
        })

所以“e”中的所有内容都将替换为“updateVal”

我尝试过的


    state.mergeWith((prev, next) => {
      if(!prev) return next;
      return next;
    }, updateVal)

这只是一个结构,“updateVal”是动态的,我不知道 updateVal 会出现什么。所以如果某些结构匹配然后替换那些特定的值

【问题讨论】:

  • 预期的输出有格式错误,我不确定在哪里。你能不能修一下。另外,请将确切的版本命名为 uf immutable.js。一些合并函数的行为从 3.8.x 到 4.0.x 略有变化

标签: javascript merge immutable.js


【解决方案1】:

mergemergeWithupdate 都执行 更新,这意味着它们只会将第一级深度的内容复制到另一个对象中。这样一来,一些值可能会丢失,因为整个地图“e”会被新地图“e”替换。

另一方面,mergeDeep 遍历并比较每个级别的集合。它将它们合并,产生您所期望的结果:

(请注意,在 ImmutableJS 版本 3.8.x 和 4.0.x 中合并有一些差异,但在这种情况下它们无关紧要)

const state = Immutable.fromJS({
  "a": "value1",
  "b": {
    "c": "value2"
  },
  "d": [],
  "e": {
    "f": "value3",
    "g": {
      "donttouchme": "ok",
      "h": true
    }
  }
});

const updateVal = Immutable.fromJS({
  "b": {
    "c": "newValue"
  },
  "e": {
    "g": {
      "h": false
    }
  }
});

const result = state.mergeDeep(updateVal);
console.log(result.toJS());
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/4.0.0-rc.14/immutable.min.js"></script>

【讨论】:

    【解决方案2】:

    我希望我能正确解释我的方法。您可能可以执行以下操作,获取对象 A 和对象 B,并使用 Proxy object with handler 基于 A 和 B 的超集创建一个新对象 C。

    你创建一个函数接受两个对象并返回一个对象。然后遍历第一个对象的键,检查第二个对象是否也具有这些键,并且当您再次遇到对象时,此调用需要递归,但我希望这对您的旅程有所帮助。如果有帮助,我也可以编写一些示例代码来分享。

    【讨论】:

    • 只有当对象是 not immutable.js immutables 时,此答案才有效。可以使用toJS 将它们转换回普通对象,然后再次使用fromJS,但对性能不利
    • 抱歉,由于某种原因,我没有看到这与 Immutable.js 对象有关。您仍然可以使用带有处理程序的 Proxy 对象进行合并,但使用 Immutable.js 内部的 mergeDeep() 函数可能会更好。我确实想说,我只是简单地尝试了 Immutable.js,它似乎通过_root.entries 确实是可变的。使用sealfreeze 可能更容易。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 1970-01-01
    • 2020-07-30
    • 2015-06-25
    • 2018-11-07
    • 2021-02-06
    相关资源
    最近更新 更多