So i am working with redux and i wrote a reducer to manage todos;
import { combineReducers } from "redux";
import { ADD_TODO, COMPELETE_TODO, REMOVE_TODO } from "./actiontypes";
const initialState = {
todos: [],
};
const rootReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TODO:
return {
...state,
todos: [...state.todos, action.payload],
};
case COMPELETE_TODO:
case REMOVE_TODO:
return {
...state,
todos: state.todos.filter(
(todo) => state.todos.indexOf(todo) != action.payload
),
};
default:
return state;
}
};
export default combineReducers({
rootReducer,
});
As you can see that I created a reducer and user combineReducer and then passed it to store in other file and it is working fine.
Now how much I understood combineReducer is that it combines seperated reducers when we write them seperately. So if i change the above reducer (as i have only single reducer) to following;
import { ADD_TODO, COMPELETE_TODO, REMOVE_TODO } from "./actiontypes";
const initialState = {
todos: [],
};
const rootReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TODO:
return {
...state,
todos: [...state.todos, action.payload],
};
case COMPELETE_TODO:
case REMOVE_TODO:
return {
...state,
todos: state.todos.filter(
(todo) => state.todos.indexOf(todo) != action.payload
),
};
default:
return state;
}
};
export default rootReducer;
And pass this to the state but it gives error. It gives undefined when i try to access todos by using useSelector;
const {todos} = useSelector(state => ({
todos: state.rootReducer.todos
}))
So what i think is i didn't understood combineReducers properly. Please explain what is causing the error above.
CodePudding user response:
Combine reducer adds namespaces to the state controlled by each reducer based on the keys of the object you pass in. When you don't use combine reducer, there won't be a namespace. So change state.rootReducer to state.
CodePudding user response:
combineReducers creates a reducer that separates the state of the combined reducers. In the documentation they show this example:
rootReducer = combineReducers({potato: potatoReducer, tomato: tomatoReducer})
which would produce the following state object
{
potato: {
// ... potatoes, and other state managed by the potatoReducer ...
},
tomato: {
// ... tomatoes, and other state managed by the tomatoReducer, maybe some nice sauce? ...
}
}
Thus when you write
combineReducers({
rootReducer,
});
The state object will be
{
rootReducer: {
// rootReducer's state
}
}
In your second example you just return the rootReducer. Therefore there are no separate states. The rootReducer operates on the root state. Thus you must adjust the selection.
const {todos} = useSelector(state => ({
todos: state.todos
}))
