在redux中克隆然后变异

时间:2017-05-30 17:21:59

标签: redux clone immutability ngrx

我一直在阅读有关redux的内容。对我来说有一件奇怪的事情。在人们给出的大多数示例中,所有复制逻辑都通过reducer处理。 我正在使用打字稿,并希望采用更基于类的方法。但也许我错过了一些东西。

假设我有一个购物车类。随着推车减速机和推车动作。 它看起来如下:

export class Cart
{
    private items:{[key:string]:number} = {};

    constructor(items:{[key:string]:number} = {})
    {
        Object.assign(this.items, items);
    }

    public addItem(id:string)
    {
        this.items[id] = this.items[id]?this.items[id]+1:1;
    }

    public removeItem(id:string)
    {
        this.items[id]--;

        if(this.items[id] <= 0)
        {
            delete this.items[id];
        }

    }

    public setItemsCount(id:string, count:number)
    {
        this.items[id] = count;
    }

    public clone():Cart
    {
        return new Cart(Object.assign({}, this.items));
    }

}

所以,我在这里将克隆逻辑包含在一个类中。

在我的减速机中,我会选择签名:

function reducer(state = new Cart(), action:Action): Cart {
    //first clone, then mutate, then return
}

或者,实际上,如何通过通用方法简单地深度克隆对象,然后改变它们然后返回?这种方法有什么不好的?

2 个答案:

答案 0 :(得分:4)

由于多种原因,这被认为是不好的做法。

首先,不鼓励将类实例保持在状态because it will break time-travel debugging。你可以这样做,但这不是“正确”的方式。

其次,你的班级正在直接改变其内容。这也将打破时间旅行调试,result in your connected React components not re-rendering properly

第三,Redux鼓励采用更具功能性的方法,而不是OOP。

您可能需要阅读我最近的两篇博客文章The Tao of Redux, Part 1 - Implementation and IntentThe Tao of Redux, Part 2 - Practice and Philosophy,其中详细介绍了Redux需要哪些技术限制以及为什么,为什么使用Redux存在常见做法,以及为什么其他方法可能可能但不被认为是惯用的。

答案 1 :(得分:1)

你可能会这样。毕竟......您将尊重Redux架构所需的不变性合同。

但我不建议你这样做。

深度克隆根本不具备高效性。您的商店越大,您的应用就越慢。

另外,为了感到荣幸我用class尝试了这种方法: https://github.com/maxime1992/pizza-sync/blob/5212a29ee9be916383f759a3a129f7b580ed32ea/frontend/src/app/shared/state/orders/orders.reducer.ts

并没有那么糟糕。但我最终使用了一个简单的功能。

有一件事,你的actions在这里打不开,这样你就会失去打字稿的一些好处。

而不是这样做,您应该为每个操作创建class,如本演讲中所述https://www.youtube.com/watch?v=cyaAhXHhxgk

另外,我已经制作了一个可以帮助您入门的ngrx启动器:https://github.com/maxime1992/angular-ngrx-starter