Home > Net >  Understanding reducers and combineReducer in redux
Understanding reducers and combineReducer in redux

Time:01-16

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
}))
  •  Tags:  
  • Related