Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my reducer returning undefined, React TypeScript

I am trying to setup my Redux store with React and TypeScript but it gives me an error that my auth reducer is undefined.

This is my store.ts:

import {Action, applyMiddleware, combineReducers, compose, createStore} from 'redux';
import { auth, IAuthState } from './Auth/reducer';
import { general, IGeneralState } from './General/reducer';

export interface IAppState {
    auth: IAuthState;
    general: IGeneralState;
}

export const rootReducer = () => combineReducers({
        auth: auth,
        general: general,
});

const store = createStore<IAppState, Action<any>, {}, {}>(
    rootReducer(),
    (window as any).__REDUX_DEVTOOLS_EXTENSION__ &&
    (window as any).__REDUX_DEVTOOLS_EXTENSION__()
);

export { store };

This is my auth reducer:

import { User } from '../../interfaces/user.interface';
import { AuthActionTypes } from './actions';

export interface IAuthState {
    user: User;
    authenticated: boolean;
}

const initialState: IAuthState = {
    user: null,
    authenticated: true,
};

export const auth = (state: IAuthState = initialState, action: any): IAuthState => {
    switch (action.type) {
        case AuthActionTypes.Setuser:
            const { User } = action.payload;

            return {
                ...state,
                user: User
            };

        case AuthActionTypes.Logout:

            return {
                ...state,
                user: null,
                authenticated: false,
            };
    }
};

It gives me the error:

Uncaught Error: Reducer "auth" 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 can use null instead of undefined.

like image 607
Jurrie Piek Avatar asked Apr 28 '26 18:04

Jurrie Piek


2 Answers

Only thing what you need to do is always return a value from the reducer, even if it is null.

The following fix will do the job:

export const auth = (state: IAuthState = initialState, action: any): IAuthState => {
    switch (action.type) {
        case AuthActionTypes.Setuser:
            const { User } = action.payload;

            return {
                ...state,
                user: User
            };

        case AuthActionTypes.Logout:

            return {
                ...state,
                user: null,
                authenticated: false,
            };
    }

    // this step was missing
    return state;
};

Few rules what you need to follow:

  1. Always needs to be returning state, even if you did not change anything, even the value is just null.
  2. You should not have return undefined.
  3. If the state has changed, you need to replace it e.g.: {...state, newValue: false}.

From documentation:

We return the previous state in the default case. It's important to return the previous state for any unknown action.

Read further: Handling Actions

I hope this helps!

like image 73
norbitrial Avatar answered Apr 30 '26 11:04

norbitrial


Reducer is a simple function that returns state no matter if it has changed or not. You are missing the default case in your reducer so just replace it with below :

export const auth = (state: IAuthState = initialState, action: any): IAuthState => {
    switch (action.type) {
        case AuthActionTypes.Setuser:
            const { User } = action.payload;

            return {
                ...state,
                user: User
            };

        case AuthActionTypes.Logout:

            return {
                ...state,
                user: null,
                authenticated: false,
            };

         default:                // this are 2 lines ive added
            return state
    }
};

Hope it helps. feel free for doubts

like image 25
Gaurav Roy Avatar answered Apr 30 '26 11:04

Gaurav Roy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!