ImmutableJS - 推入嵌套数组

时间:2017-10-09 12:49:17

标签: javascript immutability immutable.js

const List = Immutable.List;
const items = [
  { id: 1, subList: [] }, 
  { id: 2, subList: [] }, 
  { id: 3, subList: [] }
];
const newItem = { name: "sublist item" };

let collection = List(items);

collection = collection.updateIn([0, 'subList'], function (items) {
  return items.concat(newItem)
});

https://jsbin.com/midimupire/edit?html,js,console

结果:

  

错误:无效的keyPath

我想也许我需要将subList设置为List();尝试此操作时出现同样的错误。

3 个答案:

答案 0 :(得分:2)

如果我正确理解了这个问题,您希望将collection与第一个元素一起返回为:

{
  id : 1,
  subList: [
    {name: "sublist item"}
  ]
}

要做到这一点,我们需要做一些改变。

  1. 使用Immutable.fromJS将普通的JS对象数组深层转换为不可变的地图列表

  2. 使用List.update()返回包含更新值的新List

  3. 使用Map.updateIn()返回具有更新值的新LMapist

  4. 以下是整个事情:

    const List = Immutable.List;
    const items = [{
        id: 1,
        subList: []
      },
      {
        id: 2,
        subList: []
      },
      {
        id: 3,
        subList: []
      }
    ];
    const newItem = {
      name: "sublist item"
    };
    
    let collection = Immutable.fromJS(items);
    
    collection = collection.update(0, item => {
      return item.updateIn(['subList'], subList => {
        return subList.concat(newItem);
      });
    });
    
    console.log(collection)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.js"></script>

    结果:

    [
      {
        "id": 1,
        "subList": [
          {
            "name": "sublist item"
          }
        ]
      },
      {
        "id": 2,
        "subList": []
      },
      {
        "id": 3,
        "subList": []
      }
    ]
    

    更新: List.updateIn()可以使用索引作为密钥路径,因此您可以将其简化为以下内容:

    collection = collection.updateIn([0, 'subList'], subList => {
      return subList.concat(newItem);
    });
    

    像这样:

    const List = Immutable.List;
    const items = [{
        id: 1,
        subList: []
      },
      {
        id: 2,
        subList: []
      },
      {
        id: 3,
        subList: []
      }
    ];
    const newItem = {
      name: "sublist item"
    };
    
    let collection = Immutable.fromJS(items);
    
    collection = collection.updateIn([0, 'subList'], subList => {
      return subList.concat(newItem);
    });
    
    console.log(collection)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.js"></script>

答案 1 :(得分:0)

使用你得到的对象,更新subArray并返回整个对象。

const List = Immutable.List;
const items = [
  { id: 1, subList: [] }, 
  { id: 2, subList: [] }, 
  {id: 3, subList: [] }
];
const newItem = { name: "sublist item" };

let collection = List(items);

collection = collection.update([0], function (obj) {
   obj.subList = obj.subList.concat(newItem)
   return obj;
});

答案 2 :(得分:0)

这不起作用,因为Immutable.List的元素是普通的JavaScript对象(PO​​JO),而不是Immutable.Map,因此updateIn不知道如何使用他们。你可以:

  • 使用Immutable.fromJS而不是Immutable.Map作为构造函数将对象图转换为Immutable对象,从而创建对象Immutable.List。 (See JS Bin
  • 使用update([0])代替updateIn来获取POJO并对其进行变异(如@ Navjot的回答)。