Getting an error when combining two reducers using combineReducers()

Viewed 40

I'm trying to create separate reducers for different React components. This is the code:

store.tsx:

const store = createStore(rootReducer, composeWithDevTools());

root.reducers.tsx:

import { combineReducers } from 'redux';
import mainReducer from './main.reducers';
import profileReducers from './components/Profile/Profile.reducers';

const rootReducer = combineReducers({
    mainReducer,
    profileReducers,
});

export default rootReducer;

main.reducers.tsx:

<...>
function mainReducer(state = initialState, action: AnyAction) {
    switch (action.type) {
        case HOME_PAGE_MOVIES_ADDED:
            return {
                ...state,
                homePageMovies: action.homePageMovies,
            };
        case MOVIE_SELECTED:
            return {
                ...state,
                selectedMovie: action.selectedMovie,
            };

        default:
            return state;

export default mainReducer;
export type RootState = ReturnType<typeof mainReducer>;

profile.reducers.tsx:


interface mainState {
    selectedCategory: boolean;
}

const initialState: mainState = {
    selectedCategory: false,
};

function profileReducers(state = initialState, action: AnyAction) {
    switch (action.type) {
        case CATEGORY_SELECTED:
            return {
                ...state,
                selectedCategory: action.selectedCategory,
            };
        default:
            return state;
    }
}

export default profileReducers;
export type RootState = ReturnType<typeof profileReducers>;

When I try to render UI, I get following error: enter image description here

enter image description here

I get this error once I replace mainReducer by rootReducer at */store.tsx > const store = createStore(mainReducer, composeWithDevTools());.

What am i missing? Thanks!

2 Answers

In selector you need use:

state.[nameReducer].[data what you want]

If i good understand what you trying to do you need:

state.mainReducer.homePageMovies

It seems prior to using the combineReducers function to create/merge/expand your redux store's state tree you had just the single reducer.

const store = createStore(mainReducer, composeWithDevTools());

As such the state that mainReducer handled was your app's state.

const favoriteMoviesAll = useSelector(
  (state: RootState) => state.homePageMovies
);

When you start expanding the state tree you are now nesting reducers under specific keys.

const rootReducer = combineReducers({
  mainReducer,
  profileReducers,
});

const store = createStore(rootReducer, composeWithDevTools());

Now the root state is an object with mainReducer and profileReducers properties. state.homePageMovies is undefined.

const favoriteMoviesAll = useSelector(
  (state: RootState) => state.homePageMovies // undefined
);

Now favoriteMoviesAll is also undefined and can't access any slice method.

const favoriteMovies = favoriteMoviesAll.slice(0, 19); // throws error!

The same previous state that was state.homePageMovies is now nested deeper in state.mainReducer.homePageMovies.

const favoriteMoviesAll = useSelector(
  (state: RootState) => state.mainReducer.homePageMovies
);

Since this is the way react-redux works, and the naming convention for the reducer functions is <state-area>Reducer it's common to rename the reducers being passed to combineReducers to give them more readable names that make sense in a state tree.

Example:

const rootReducer = combineReducers({
  movies: mainReducer,
  profile: profileReducers,
});

...

const favoriteMoviesAll = useSelector(
  (state: RootState) => state.movies.homePageMovies
);
Related