javascript - Redux 状态正在随着 lodash 的 mergeWith 发生变化

标签 javascript redux lodash

我正在使用 lodash 的 mergeWith 将一些负载数据合并到我的一些 redux 状态中。然而,当这样做时,我最终会直接改变状态。我不明白这是如何发生的,因为我使用 {...state} 来进行合并。为什么会发生这种情况?我该怎么做才能不直接改变我的状态?您可以查看下面的代码片段,了解正在发生的情况的示例。谢谢!

const merger = (objectOne, objectTwo) => {
  const customizer = (firstValue, secondValue) => {
    return _.isArray(firstValue) ? secondValue : undefined;
  };

  return _.mergeWith(objectOne, objectTwo, customizer);
};

const state = {
  1: {a: true, b: true, c: true},
  2: {a: true, b: true, c: true},
  3: {a: true, b: true, c: true},
}

const payload = {
   2: {a: true, b: false, c: true},
}

console.log("Merged data:");
console.log(merger({...state}, payload));
console.log("Manipulated state:");
console.log(state);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>

最佳答案

这是一个简单的问题:

let a = { foo: 'A'}
let c = { ... a }  // shallow copy of a

a.foo = 'boo'

console.log(a)
console.log(c) // works as expected c.foo is NOT changed and still is 'A'

正如您从上面的示例中看到的,具有传播和基于值的属性的浅复制可以按预期工作。然而,当你这样做时:

let x = { foo: { boo: 'A' }}  // object as value this time
let y = { ... x }  // shallow copy of x

x.foo.boo = 'beer'

console.log(x.foo.boo)
console.log(y.foo.boo) // should be 'boo' but it is 'beer'

浅复制效果不佳,因为克隆具有指向旧x对象而不是克隆对象的引用。

要解决此问题并让您的代码更加简洁,您可以:

const state = { 1: {a: true, b: true, c: true}, 2: {a: true, b: true, c: true}, 3: {a: true, b: true, c: true}, }
const payload = { 2: {a: true, b: false, c: true} }

const merger = (...args) => _.mergeWith(...args, (a,b) => _.isArray(a) ? b : undefined)

console.log("Merged data:");
console.log(merger(_.cloneDeep(state), payload));
console.log("Manipulated state:");
console.log(state);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

第一次切换lodash _.cloneDeep这将深度复制整个对象树,并且您还可以使用 ES6 spread 等使您的 merge 方法更加简洁。

关于javascript - Redux 状态正在随着 lodash 的 mergeWith 发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53603880/

相关文章:

javascript - 放大CSS HTML时如何阻止DIV粘在页面左侧

javascript - 如何设置除底部边框之外的所有边框宽度

reactjs - 在每次测试之前手动修改initialState并将其传递给商店?

redux - 如何正确输入传奇

javascript - 如何指定 html slider 显示的时间来自动跳过它?

JavaScript 意外行为 2 个问题(数学错误且未显示简单结果)

reactjs - Redux 避免陈旧数据?

javascript - _.pluck 在找不到对象时给出一个未定义值的数组

javascript - 如何使用 lodash 将两个数组(数组 1d 和数组 2d 对象)合并为数组

javascript - 使用 API 删除有时有效有时无效