如何更新不可变List以获取新列表

Sal*_*man 6 javascript immutable.js

我有一个不可变Map的如下

var mapA = Map({
  listA: List.of({
    id: 1,
    name: 'Name A',
    selected: false
  }, {
    id: 2,
    name: 'Name B',
    selected: false
  })
});
Run Code Online (Sandbox Code Playgroud)

我想更新selected列表中的密钥.根据immutable.js文档list.update.

返回一个新的List,其索引处的更新值带有调用updater的返回值

但是,如果我这样做

var listB = mapA.get('listA').update(1, function (item) {
    item.selected = true;
    return item;
});
Run Code Online (Sandbox Code Playgroud)

并且,检查对象是否相等,它给了我true.

console.log(listB === x.get('listA')); // true
Run Code Online (Sandbox Code Playgroud)

我在这做错了什么?是不是应该如何使用immutable.js?

Fel*_*ing 1

问题是您在不可变列表中使用可变值。对于列表,对象不会改变,因为oldObject === newObject仍然是 true。

这是一个简化的示例:

> var obj = {};
> var list = Immutable.List.of(obj);
> list2 = list.update(0, function(obj) { obj.foo = 42; return obj;});
> list2.get(0)
Object { foo: 42 }
> obj
Object { foo: 42 }
> list.get(0) === list2.get(0)
true
Run Code Online (Sandbox Code Playgroud)

要解决这个问题,除了更新地图(如果你想要的话)之外,你还必须

  • 更新时克隆对象
  • 使用 Map 而不是对象
  • 在这种情况下可能最好:使用记录不是对象

例子:

var MyRecord = new Immutable.Record({id: null, name: '', selected: false});

var mapA = Immutable.fromJS({
  listA: [
    new MyRecord({
      id: 1,
      name: 'Name A'
    }),
    new MyRecord({
      id: 2,
      name: 'Name B'
    })
  ]
});

var mapB = mapA.updateIn(['listA', 1], function(record) {
  return record.set('selected', true);
});

console.log(mapB.get('listA') === mapA.get('listA')); // false
Run Code Online (Sandbox Code Playgroud)