微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

javascript – 更新ngrx / store中的对象

我正在使用@ ngrx / store来购买Angular 2应用程序.

我的商店拥有一个说明书,Book对象的列表.我想更新其中一个对象中的字段.我也碰巧有一个我想要更新的Book实例的Observable(比如,selectedBook).

为了进行更新,我打算使用UpdateBookAction调用reducer,以及新Book的有效负载.所以我通过订阅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)进行深层复制(而不是改变旧版本!),然后将更新仅发布到我想要触摸的字段.

解决方法

ngrx商店的想法是拥有一个且只有一个真实的地方,这意味着所有对象都是不可变的,改变任何东西的唯一方法就是重新创建整个事物.此外,您可能正在使用ngrx freeze( https://github.com/codewareio/ngrx-store-freeze),这意味着所有对象都将以只读方式创建,因此您无法更改任何对象(如果您想完全遵循redux模式,这对开发有利).如果您删除商店冻结对象的部分,您将能够更改它,但这不是最佳实践.

我建议您使用以下内容:使用带有异步管道的ngrx observable将数据(在您的案例中)放入一个只能输入和输出某个事件的哑组件中.在哑组件内部,您可以通过复制它来“编辑”该对象,并在完成后,您可以将更改发回到订阅商店的智能组件并允许其更改状态通过商店(提交).这种方式是最好的,因为对于一个非常小的更改来改变整个状态并不常见(比如双向绑定,当用户输入时……).

如果您遵循redux模式,那么您将能够添加历史记录,这意味着商店将保留最后X个状态重新创建的副本,因此您可以获得UNDO功能,更易于调试,时间线等

您的问题是您正在直接编辑属性而不是重新创建整个状态.

原文地址:https://www.jb51.cc/js/153522.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐