Javascript Immutable.js允许对象的变异

Javascript Immutable.js允许对象的变异,javascript,immutable.js,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不应更改 多亏了帮助者。所有这一切都是因为您的有效负载不是不可变的对象。同样的事情,

下面是一个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
不应更改


多亏了帮助者。

所有这一切都是因为您的有效负载不是不可变的对象。同样的事情,没有太多的背景:

const a = {'foo': 'bar};
不能将值重新分配给like
a='baz'a
是一个常数。但是您可以更改
a.foo
的值,因为它不是常量/不可变的。您可以使用
a.foo='baz'和它将工作。因此,您正在对immutableJs执行相同的操作。如果您想拥有完整的不可变结构,请将负载也转换为不可变。您已经更新了值,因为immutablejs持有指向源变量的指针,而不创建该值的新本地实例

简言之,在使用有效载荷之前,先使用
payload=Immutable.fromJS(有效载荷)
,这样所有结构都是不可变的

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());

所有这一切都是因为您的负载不是不可变的对象。同样的事情,没有太多的背景:

const a = {'foo': 'bar};
不能将值重新分配给like
a='baz'a
是一个常数。但是您可以更改
a.foo
的值,因为它不是常量/不可变的。您可以使用
a.foo='baz'和它将工作。因此,您正在对immutableJs执行相同的操作。如果您想拥有完整的不可变结构,请将负载也转换为不可变。您已经更新了值,因为immutablejs持有指向源变量的指针,而不创建该值的新本地实例

简言之,在使用有效载荷之前,先使用
payload=Immutable.fromJS(有效载荷)
,这样所有结构都是不可变的

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());

您对“不可能”的评论是什么意思?有效负载只是一个普通变量,它不会因为您使用它初始化不可变的东西而变得不可变。@tevemadar注释令人困惑。我的意思是它不应该影响newState。你对“不可能”的评论是什么意思?有效负载只是一个普通变量,它不会因为您使用它初始化不可变的东西而变得不可变。@tevemadar注释令人困惑。我的意思是它不应该影响newState。这和问题中的代码不太一样。。。负载显然是一个具有id属性的对象,OP是changingtanks@LukasLiesis,这很有意义。我必须补充一点,当对“state.merge(payload)”执行相同操作,然后尝试更改
有效负载时,这不会更改存储。这与问题中的代码不太一样。。。负载显然是一个具有id属性的对象,OP是changingtanks@LukasLiesis,这很有意义。我必须补充一点,当对“state.merge(payload)”执行相同操作,然后尝试更改
有效负载时,这不会更改存储。