Clone and then mutate approach in redux

时间秒杀一切 提交于 2019-12-11 06:13:59

问题


I've been reading stuff on redux for a while. And there is a strange thing for me. In most examples people give, all the copying logic is handled via reducers. I'm using typescript and want to adopt a more class-based approach. But maybe I'm missing something.

Let's say I have a shopping Cart class. Along with cart reducer and cart actions. It looks the following way:

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));
    }

}

So, here I'm incapsulating cloning logic in a class.

And in my reducer I would go with the signature:

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

Or, actually, how about simply deep-cloning objects via a universal method, then mutating them and then returning? What's bad about that approach?


回答1:


This is considered bad practice for several reasons.

First, keeping class instances in state is discouraged because it will break time-travel debugging. You can do it, but it's not the "right" way.

Second, your class is directly mutating its contents. This will also break time-travel debugging, and result in your connected React components not re-rendering properly.

Third, Redux encourages a more functional approach, not OOP.

You may want to read through my two recent blog posts, The Tao of Redux, Part 1 - Implementation and Intent and The Tao of Redux, Part 2 - Practice and Philosophy, which go into detail on what technical limitations Redux requires and why, why common practices exist for using Redux, and why other approaches may be possible but are not considered idiomatic.




回答2:


You might go this way. After all ... You'll respect the immutability contract needed by Redux architecture.

But I wouldn't recommend you to do that.

Deep cloning is not performant at all. The bigger is your store, the slower will be your app.

Plus, to be honnest I tried this approach with a class : https://github.com/maxime1992/pizza-sync/blob/5212a29ee9be916383f759a3a129f7b580ed32ea/frontend/src/app/shared/state/orders/orders.reducer.ts

And it's not so bad. But I ended up using a simple function.

One thing tho, your actions here won't be typed so you will loose some benefits of Typescript.

Instead of doing that, you should create a class per action, as explained in this talk https://www.youtube.com/watch?v=cyaAhXHhxgk

Also, I've made an ngrx starter that might help you get started : https://github.com/maxime1992/angular-ngrx-starter



来源:https://stackoverflow.com/questions/44268317/clone-and-then-mutate-approach-in-redux

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!