Monday, May 14, 2018

Mutating Redux state

Mutating Redux state directly does not work.

export interface ICounterMore
{
    count: number;
    message: string;
}

export function counterReducer(
    state: ICounterMore = {count: 0, message: 'hello'},
    action: ICounterAction
): ICounterMore
{
    switch (action.type) {
        case CounterKind.INCREMENT:
            state.count = state.count + 1;
            return state;
        case CounterKind.DECREMENT:
            state.count = state.count - 1;
            state.message = 'hey';
            return state;
        default:
            return state;
    }
}


Must return new state that does not mutate the existing state.

export function counterReducer(
    state: ICounterMore = {count: 0, message: 'hello'},
    action: ICounterAction
): ICounterMore
{
    switch (action.type) {
        case CounterKind.INCREMENT:
            return {
                ...state,
                count: state.count + 1
            };
        case CounterKind.DECREMENT:
            return {
                ...state,
                count: state.count - 1,
                message: 'hey'
            };
        default:
            return state;
    }
}


Mutating Redux state "directly" works, using immer.

immer creates immutable state from the mutated state from draft, and then it return the immutable state to Redux.
Proof that immutable state is the state that is still being passed around, Redux's time travel still work.


export function counterReducer(
    state: ICounterMore = {count: 0, message: 'hello'},
    action: ICounterAction
): ICounterMore
{
    return produce(state, draft => {
        switch (action.type) {
            case CounterKind.INCREMENT:
                ++draft.count;
                break;
            case CounterKind.DECREMENT:
                --draft.count;
                draft.message = 'hey';
                break;
        }
    });
}

Happy Coding!

No comments:

Post a Comment