Adding Recipes

Implement the function to add recipes to the app you are creating.

To implement adding recipes, we need to find a way to modify our store. reducers can only do store modifications in response to actions. This means we need to define an action structure and modify our reducer to support it.

Actions in Redux are nothing more than plain objects that have a mandatory type property. We will be using strings to name our actions, with the most appropriate in this case being 'ADD_RECIPE'. Since a recipe has a name, we will also add that to the action’s data when dispatching:

store.dispatch({ type: 'ADD_RECIPE', name: 'Pancakes' });

Let’s modify our reducer to support the new action. A simple approach might appear to be the following:

const reducer = (state, action) => {
  switch (action.type) {
    case 'ADD_RECIPE':
      state.recipes.push({ name: action.name });
  }

  return state;
};

While this looks correct, this code violates the basic Redux principle of state immutability. Our reducers must never change the state but only create a new version of it, with any modifications needed. Thus, our reducer code needs to be modified:

const reducer = (state, action) => {
  switch (action.type) {
    case 'ADD_RECIPE':
      return Object.assign({}, state, {
        recipes: state.recipes.concat({ name: action.name })
      });
  }

  return state;
};

Although the 'ADD_RECIPE' case has become more complex, it works exactly as expected. We are using the Object.assign() method to create a new object with all the key/value pairs from our old state that also overrides the recipes key with a new value.

To calculate the new list of recipes, we use concat() instead of push(), as push() modifies the original array while concat() creates a new array containing the original values and the new one.

Get hands-on with 1200+ tech skills courses.