-1

I'm learning React and I have a good portion of my program working, but there is one piece that is not updating when I update the state and I'm not sure why.

I have a list of ingredients, a list of recipes (that contain ingredients) and a shopping list that contains a list of ingredients with a quantity combined with all of the recipes that are added to the shopping list.

I'm storing all of this in state

state = {
    ingredients: {},
    instructions: {},
    recipes: {},
    shoppingList: {
      ingredients: {}
    }
  }

When I add a recipe, add ingredients to the recipe and add the recipe to the shopping list, this is what the state looks like. If I modify the recipe to require 2 tomatoes instead of 1, the shopping list updates. However, if I add a new ingredient to the recipe, the shopping list does not update with the new ingredient. I'm not sure why...

f

Here is the rest of the code to the program:

addRecipe = recipe => {
    // copy state
    const recipes = { ...this.state.recipes };
    // add recipe to copy
    recipes[`recipe${Date.now()}`] = recipe;
    // set state
    this.setState({ recipes: recipes });
  }

  loadSampleRecipes = () => {
    this.setState({ recipes: sampleRecipes });
  }

  addIngredient = ingredient => {
    // copy state
    const ingredients = { ...this.state.ingredients };
    // add ingredient to copy
    ingredients[`ingredient${Date.now()}`] = ingredient;

    // set state
    this.setState({ ingredients: ingredients });
  }

  updateIngredient = ingredient => {
    // copy state
    const ingredients = { ...this.state.ingredients };

    ingredients[ingredient].price = 99;

    // set state
    this.setState({ ingredients: ingredients });
  }

  loadSampleIngredients = () => {
    this.setState({ ingredients: sampleIngredients });
  }

  addIngredientToRecipe = (recipe, ingredient) => {
    // copy state
    const recipes = { ...this.state.recipes };

    // add ingredient
    recipes[recipe].ingredients[ingredient] = this.state.ingredients[ingredient];
    recipes[recipe].ingredients[ingredient].qty = recipes[recipe].ingredients[ingredient].qty + 1 || 1; // not sure if this is needed
    // set state
    this.setState({ recipes: recipes });
  }

  deleteIngredientFromRecipe = (recipe, ingredient) => {
    // copy state
    const recipes = { ...this.state.recipes };

    // remove ingredient from recipe
    delete recipes[recipe].ingredients[ingredient];

    // set state
    this.setState({ recipes: recipes });
  }

  addIngredientsToShoppingList = (ingredients) => {
    // copy state
    const shoppingList = { ...this.state.shoppingList}

    // add ingredient or increase qty
    Object.keys(ingredients).forEach(ingredient => {
      const newIngredient = ingredients[ingredient] // copy current incoming ingredient

      // add qty together
      if (shoppingList.ingredients[ingredient]) {
        shoppingList.ingredients[ingredient].qty += newIngredient.qty;
      } else {
        shoppingList.ingredients[ingredient] = newIngredient;
      }
    });
    console.log(shoppingList);

    // set state
    this.setState({ shoppingList: shoppingList });
  }
Yitzhak
  • 343
  • 1
  • 4
  • 16

1 Answers1

1

Assuming that you use the useState hook

setState({incredients: incredients}) 

destroys the state as all properties but incredients are lost. In order to update the incredients you would use

setState({                      // create new state  
    ...state,                   // spread the current state, keeps unchanged props
    incredients: incredients    // overwrite the changed property
})

You got the same problem when updating the recipies and shoppingList. See Updating an object with setState in React for a thorough explanation.

chriopp
  • 947
  • 7
  • 12
  • 1
    Calling `setState` with just one property only changes that one property. It doesn't "destroy" the other properties. Example: https://jsfiddle.net/y4wqh328/ – Cully May 18 '20 at 06:13
  • @Cully Thank you for the comment. This is different if you use the useState hook. – chriopp May 18 '20 at 06:30
  • Yes, `useState` works differently. But the OP is using `setState`. – Cully May 18 '20 at 06:56