开发者问题收集

向不可变列表添加单个元素

2017-08-21
2972

我只想将一个元素添加到我的不可变对象树中某处的列表中。

这个问题似乎已经在这里得到回答:

将值附加到列表

但由于某种原因,它对我来说不起作用。

如果我有以下代码:

var myState = {
  a: {
    b: {
      c: [
        {name: 'hi', value: 2},
        {name: 'howdy', value: 3}
      ]
    }
  }
}
myState = Immutable.fromJS(myState);
myState = myState.update(['a', 'b', 'c'], function (myList) {
  myList.push({"name": "hallo", "value": 4})
  }
);

我收到错误:

Uncaught TypeError: Cannot read property 'push' of undefined

这表明传递到回调中的 myList 参数为空。

为什么会发生这种情况?

小提琴:

https://codepen.io/owatkins/pen/brMava

2个回答

应这样写:

myState.updateIn(['a', 'b', 'c'], function (myList) {
    return myList.push({"name": "hallo", "value": 4})
  }
);

下面是一个工作示例:

var myState = Immutable.fromJS({
  a: {
    b: {
      c: [{
          name: 'hi',
          value: 2
        },
        {
          name: 'howdy',
          value: 3
        }
      ]
    }
  }
})

myState = myState.updateIn(['a', 'b', 'c'], function(myList) {
  return myList.push({
    "name": "hallo",
    "value": 4
  })
});

console.info('myState = ' + myState.toJS())
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.min.js"></script>

请注意,我使用的是 updateIn 而不是 update ,并返回 push 的结果

thedude
2017-08-22

经过一番折腾,我能想到的唯一解决方案是获取数组,然后转换为 JS,将元素推送到该数组上,然后将其转换回不可变数组...然后使用 setIn ,而不是 updateIn ,也不是 update

var myState = {
  a: {
    b: {
      c: [
        {name: 'hi', value: 2},
        {name: 'howdy', value: 3}
      ]
    }
  }
}
myState = Immutable.fromJS(myState);

var list = myState.getIn(['a', 'b', 'c'])
var list = list.toJS();

list.push({"name": "hallo", "value": 4});

var v = Immutable.fromJS(list)

myState = myState.setIn(['a', 'b', 'c'], v)

这看起来像是一个糟糕的解决方案,但到目前为止,这是对我唯一有效的方法。

通常需要大约 5 分钟才能学会如何在框架或语言中将元素添加到列表中。

我没想到会花 5 小时

这个框架的文档简直是耻辱。

Oliver Watkins
2017-08-22