【问题标题】:ImmutableJS - pushing into a nested arrayImmutableJS - 推入嵌套数组
【发布时间】:2017-10-09 12:49:16
【问题描述】:
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();我在尝试这个时遇到了同样的错误。

【问题讨论】:

  • 哪个键导致错误?
  • 很难说 (github.com/facebook/immutable-js/issues/635)。我知道使用最新的不可变在本地运行它,问题是 [0] 无法设置
  • updateIn 更改为getIn,并尝试删除“subList”键。它会返回第一张地图吗?

标签: javascript immutability immutable.js


【解决方案1】:

如果我对问题的理解正确,您想返回collection,第一个元素为:

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

为此,我们需要进行一些更改。

  1. 使用 Immutable.fromJS 将纯 JS 对象数组深度转换为不可变的 Map 列表

  2. 使用List.update() 以返回具有更新值的新List

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

这就是全部内容:

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>

【讨论】:

    【解决方案2】:

    使用你得到的对象,更新 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;
    });
    

    【讨论】:

      【解决方案3】:

      这不起作用,因为 Immutable.List 的元素是普通的 JavaScript 对象 (POJO),而不是 Immutable.Maps,所以 updateIn 不知道如何使用它们。您可以:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-06-14
        • 2022-06-10
        • 1970-01-01
        • 2018-01-27
        • 2018-06-26
        • 2021-02-10
        相关资源
        最近更新 更多