Search code examples
react-nativereduxreact-reduxstatereduce

Understanding reducers and combineReducer in redux


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.


Solution

  • 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.