Search code examples
javascripttypescriptredux

Reducer "loading" returned undefined during initialization - combineReducers


I'm trying to create a destination if there is none with that name in the list. The creation fails with error:

Reducer "loading" returned undefined during initialization. If the state passed to the reducer is undefined, you must explicitly return the initial state. The initial state may not be undefined. If you don't want to set a value for this reducer, you ...

I tracked the issue down to combineReducers, more speficially the reducers loading and errors. Both give same error, if the other one is commented out. If both are commented out, then the program seems to work, but I assume they are here for a bigger reason and removing them isn't an option.

Havent found a solution or a bigger clue from other similar posts (how would you even fit an initialState next to TState?). Also, this is the first time I work with Typescript and Redux in my short coder career, so the solution may be obvious for somebody, but I've struggled with it the whole day today. So, please help...

DestinationCreateView.js

const reducer = combineReducers({
    destinationReducer,
    loading,
    errors,
});

errorReducer.ts (loadingReducer.ts is almost identical)

import type { PayloadAction, SerializedError } from '@reduxjs/toolkit';

export default <TState>(state: TState & { errors: Record<string, unknown> }, action: PayloadAction) => {
    const { type, payload } = action;
    const matches = /\[(.*)]\s(TRIGGER|REQUEST|FAILURE)([_\w]+)*/.exec(type);

    if (!matches) return state;

    const [, stateKey, requestState, extra] = matches;
    const storageKey = extra ? `${stateKey}-${extra.substr(1).toLowerCase()}` : stateKey;
    return {
        ...state,
        errors: {
            ...state.errors,
            [storageKey]: requestState === 'FAILURE' ? payload : null,
        },
    };
};
...

Solution

  • Replacing combineReducers with reduceReducers did the thing:

    const reducer = reduceReducers(
        {
            ...initialState,
            loading: { [DESTINATION_DUCK_PREFIX]: true },
            errors: {},
        },
        destinationReducer,
        loading,
        errors,
    );