Home > OS >  Can't use multiple reducers with combineReducers, getting an unknown property warning on state
Can't use multiple reducers with combineReducers, getting an unknown property warning on state

Time:02-01

I have my store set up as follows:

const rootReducer = combineReducers({
    login: loginReducer,
    counter: counterReducer
});

const store = configureStore({
    reducer: rootReducer
});

The login reducer/slice looks as follows:

import { createSlice } from '@reduxjs/toolkit';

const loginSlice = createSlice({
    name: 'login',
    initialState: {
        isLoggedIn: false,
    },
    reducers: {
        login: (state) => {
            state.isLoggedIn = true;
        },
        logout: (state) => {
        state.isLoggedIn = false;
        },
    },
});

export const { login, logout } = loginSlice.actions;

export default loginSlice.reducer;

The counter reducer/slice looks as follows:

import { createSlice } from '@reduxjs/toolkit';

export const counterSlice = createSlice({
    name: 'counter',
    initialState: {
        counterValue: 0,
    },
    reducers: {
        increment: (state) => {
            state.counterValue  = 1;
        },
        decrement: (state) => {
            state.counterValue -= 1;
        },
        incrementByAmount: (state, action) => {
            state.counterValue  = action.payload;
        },
    },
});

export const { increment, decrement, incrementByAmount } = counterSlice.actions;

export default counterSlice.reducer;

The problem now is that I can't access the values from these two reducers this way, which should be the right way (also according to the Redux Devtools):

const counterValue = useSelector((state) => state.counter.counterValue);
const counterValue = useSelector((state) => state.login.isLoggedIn);

Doing something like this:

const counterValue = useSelector((state) => state.counterValue);
const isLoggedIn = useSelector((state) => state.login.isLoggedIn);

... returns undefined, but trying to do state.counter.counterValue or state.login.isLoggedIn gives me the error of unknown property on state.

I get an error saying Property 'counter' does not exist on type 'unknown'.. I'm using Typescript, and maybe the unknown type of state is the issue, but not sure and no idea how to fix that if that's the problem. Why are the properties given in the combineReducers call unknown on the state object when trying to access them?

CodePudding user response:

Since you are using TypeScript, you should consider following the redux recommendations and create typed RootState and store hooks.

As a part of your store setup:

const store = configureStore(...)

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch

// Use throughout your app instead of plain `useDispatch` and `useSelector`
type DispatchFunc = () => AppDispatch
export const useAppDispatch: DispatchFunc = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

RootState will be a type that is inferred from the state defined for each slice. In your example, state.login and state.counter. useAppSelector is then a type safe and convenient way of using useSelector((state: RootState) => ...), allowing:

const counterValue = useAppSelector(state => state.counter.counterValue);
const isLoggedIn = useAppSelector(state => state.login.isLoggedIn);
  • Related