Immutable.js允许变异对象

时间:2017-10-30 09:54:23

标签: javascript immutable.js

以下是Redux reducer的示例:

case REDUCE_ME:
  const newState = state.setIn(['a', 'b', 'c'], payload);
  payload.id = 'I MANIPULATE STORE!'; 
  return newState; // newState.a.b.c.id is 'I MANIPULATE STORE!'

预期行为:id不应更改。

感谢帮助者。

1 个答案:

答案 0 :(得分:2)

所有这一点都是因为您的有效负载不是不可变对象。同样的事情与更少的背景:

const a = {'foo': 'bar};

您无法为a = 'baz';之类的值重新分配值,因为a是常量。但是您可以更改a.foo的值,因为它不是常量/不可变的。您可以使用a.foo = 'baz';,它会起作用。所以你用immutableJs做同样的事情。如果要拥有完全不可变结构,请将有效负载转换为不可变。并且您已更新了值,因为immutablejs包含指向源变量的指针,而不创建该值的新本地实例。

简而言之 - 在使用有效负载之前使用payload = Immutable.fromJS(payload),您可以将所有结构都视为不可变。

const state1 = new Immutable.fromJS({
   a: {
       b: {
           c: 'foo'
       }
   }
});

console.log('State 1', state1.toJS());

let payload = 'bar';
const state2 = state1.setIn(['a','b','c'], payload);
console.log('state2 after 1st change',state2.toJS());

payload = 'baz';

console.log('state2 adter 2nd change',state2.toJS()); // c will be still bar

let payload2 = {'a': 'bar'};
// attaching payload2 which can not be changed from object to something else but it's inside values can be changed.
// same like with const a = {'foo': 'bar}; you cant re-assign value to a, but you can modify a.foo = 'whatever else';
const state3 = state1.setIn(['a','b','c'], payload2);  
console.log('state3 after 1st change',state3.toJS());

payload2.a = 'baz';
console.log('state3 after 2nd change (switched to baz)',state3.toJS());

payload2 = 'baz';
console.log('state3 after 3rd change (tried to set payload2 to string)',state3.toJS());

https://codepen.io/anon/pen/bYNWNr