Search code examples
javascriptangulartypescriptreduxngrx

Ngrx createReducer migrating from earlier version


I am having difficulties in migrating the reducer code to use createReducer(), specially for the default case.

export function reducer(
    state: { [key: string]: any },
    action: FormActions
): { [key: string]: any } {
    const newState = _.cloneDeep(state);

    switch (action.type) {
        case FormActionTypes.UpdateValue: {
            return fieldUpdateReducer(newState, action as UpdateValue);
        }

        case RESET_WIZARD:
        case WizardActionTypes.ResetWizard: {
            return {};
        }

        default: {
            return fromForm.reducer(state, action as FormActions);
        }
    }
}

I tried to change it like below, but the unit test for the default case is failing. I am here trying to call other reducer in case of default option.

export const createClusterFormReducer = createReducer(
    (state, action) => fromForm.reducer(state, action),
    on(updateValue, (state: { [key: string]: any }, action: Action) => {
        const newState = _.cloneDeep(state);
        return fieldUpdateReducer(newState, action);
    }),
    on(resetWizard, (state, action) => {
        return {};
    }),
    on(wizardActionsResetWizard, (state, action) => {
        return {};
    })
);
export function reducer(
    state: { [key: string]: any },
    action: Action
): { [key: string]: any } {
    return createClusterFormReducer(state, action);
}

Solution

  • There is no default case with createReducer, but there are some options to support this.

    You can create a higher order reducer though.

    Or add other on methods by using the spread operator.

    export const createClusterFormReducer = createReducer( (state, action) => fromForm.reducer(state, action), on(updateValue, (state: { [key: string]: any }, action: Action) => { const newState = _.cloneDeep(state); return fieldUpdateReducer(newState, action); }), on(resetWizard, (state, action) => { return {}; }), ...otherOnMethods );

    Maybe the simplest is to create a meta reducer.

    export function reducer(
        state: { [key: string]: any },
        action: Action
    ): { [key: string]: any } {
        const newState = createClusterFormReducer(state, action);
        if(newState === state) {
           return otherReducer(state,action)
        }
        return newState;
    }