用新值更新不可变的 js 嵌套对象
Posted
技术标签:
【中文标题】用新值更新不可变的 js 嵌套对象【英文标题】:Update immutable js nested object with new value 【发布时间】: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 略有变化 【参考方案1】:merge
mergeWith
和update
都执行浅 更新,这意味着它们只会将第一级深度的内容复制到另一个对象中。这样一来,一些值可能会丢失,因为整个地图“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
确实是可变的。使用seal 和freeze 可能更容易。以上是关于用新值更新不可变的 js 嵌套对象的主要内容,如果未能解决你的问题,请参考以下文章
在 React/Redux reducer 中,如何以不可变的方式更新嵌套数组中的字符串?
在 Immutable.js 中使用 React 的不可变助手