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:
I get this error once I replace mainReducer
by rootReducer
at */store.tsx
> const store = createStore(mainReducer, composeWithDevTools());
.
What am i missing? Thanks!
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
);