# Redux Tutorial: Define Reducers

Step 1: Create redux-todolist/src/redux/reducers/todos.js

First, let's define a reducer for our Todo type. To do that, create a file redux-todolist/src/redux/reducers/todo.js. Once created, open the file in your favorite editor and add the following code:


import {
  ALL_TODOS,
  EDIT_TODO,
  REMOVE_TODO,
  SINGLE_TODO,
  CREATE_TODO,
} from '../actions/actionTypes';

function getIndexOfTodoItem(action, state) {
  let index = -1, data = action.result;

  for (let i = 0; i < state.result.length; i++) {
    if (state.result[i]._id === data._id) {
      index = i;
      break;
    }
  }

  return index;
}

function todos(state = [], action) {
  if (action.error) {
    return {
      result: state.result,
      error: action.error,
    };
  }

  switch(action.type) {
    case SINGLE_TODO:
    case ALL_TODOS:
      return {
        result: action.result
      };
    case CREATE_TODO:
      return {
        result: [
          ...state.result,
          action.result,
        ]
      };
    case EDIT_TODO:
      var index = getIndexOfTodoItem(action, state);

      // todo item not found in state object so return original state
      if (index === -1) return state;

      // todo item found! return new state
      return {
        result: [
          ...state.result.slice(0, index),
          Object.assign({}, state.result[index], action.result),
          ...state.result.slice(index + 1)
        ]
      };
    case REMOVE_TODO:
      var index = getIndexOfTodoItem(action, state);

      // todo item not found in state object so return original state
      if (index === -1) return state;

      // todo item found! don't include it in the new state
      return {
        result: [
          ...state.result.slice(0, index),
          ...state.result.slice(index + 1)
        ],
      };
    default:
      return state;
  }
}

module.exports = {
  todos,
};

Let's breakdown the above code:

  • If the action dispatches an error, we just return the new state with the error details.

  • If the action did not dispatch an error, we check the action type and return the new state accordingly. The action types we defined in the "Define Action Types" section are: SINGLE_TODO, ALL_TODOS, EDIT_TODO and REMOVE_TODO.

  • For SINGLE_TODO, we just return the result from the action as the result contains the Todo item.

  • For CREATE_TODO, we append the result to the current state and return the new state.

  • For EDIT_TODO, we get the index item of the todo fetched from the action and then modify the todo item with the new data. We then return a new state with the modified todo item.

  • For REMOVE_TODO, we get the index item of the todo fetched from the action and then return a new state without the index item.

Step 2: Import into: redux-todolist/src/redux/reducers/index.js

Open redux-todolist/src/redux/reducers/index.js and import the reducer file defined above. Your index.js file should look something like this:


import todos from './todos';

module.exports = {
  ...todos,
};

With the action types, actions and reducers defined, let us head on to the next section which deals with creating basic UI components for our todolist application.