【发布时间】:2017-04-15 10:54:49
【问题描述】:
我将 @ngrx/store 用于 Angular 2 应用程序。
我的商店有一个 Book 对象列表。我想更新其中一个对象中的字段。我也碰巧有一个我想要更新的 Book 实例的 Observable(比如,selectedBook)。
为了进行更新,我打算使用UpdateBookAction 和新书的有效负载调用reducer。因此,我通过订阅 selectedBook 然后调用 Object.assign() 对现有 Book 对象进行深拷贝。
但是当我尝试写入副本的其中一个字段时,我收到以下错误。 (如果我尝试直接写入商店中的 Book 对象,这恰好是同样的错误。)
错误
Cannot assign to read only property 'name' of object '#<Object>' at ViewWrappedError.BaseError [as constructor]
代码
ngOnInit() {
this.book$ = this.store.let(fromRoot.getSelectedBook);
//...
}
someFunction() {
//...
this.book$.subscribe(book => {
let updatedBook = Object.assign({}, book);
updatedBook.name = 'something else'; // <--- THIS IS WHAT THROWS
let action = new BookUpdateAction(updatedBook);
this.store.dispatch(action);
}
}
评论后的澄清
我假设我可以使用不是商店的整个状态的有效负载进行操作。 (事实上,这似乎是必要的,不是吗?)鉴于文档,我相信情况就是如此。
我希望采取的行动是这样的:
Action = UPDATE, payload = {'id': 1234, 'name': 'something new'}
如前所述,我打算这样打电话:
this.store.dispatch(action);
大概在幕后,ngrx 正在将我的操作与(不可变的)当前状态一起传递给减速器。
所以从那里开始,一切都应该可以正常工作。我在 reducer 中的逻辑不会改变现有状态,它只是从现有状态和我传入的有效负载中创建一个新状态。
这里真正的问题是如何合理地构建新的“objectToUpdate”,以便可以将其作为有效负载传递。
我可以这样做:
this.book$.subscribe(book => {
let updatedBook = new Book();
updatedBook.id = book.id;
//set all other fields manually...
updatedBook.name = 'something else';
let action = new BookUpdateAction(updatedBook);
this.store.dispatch(action);
}
但我们在这里讨论的不仅仅是两个领域……如果我的书有多个领域怎么办?我是否必须每次都从头开始手动构建一本新书才能更新一个字段?
我的解决方案是使用 Object.assign({}, book) 进行深层复制(而不是改变旧的!),然后仅对我希望接触的字段进行更新。
【问题讨论】:
-
能否贴出 book 对象的定义?似乎这可能是只写属性的问题。
-
是的,看看书的定义会很有帮助。在一次通话中完成所有操作时,您是否有同样的问题?例如
Object.assign({}, book, { name: 'something else' })?
标签: javascript angular typescript rxjs ngrx