I have 2 states, but both are updating even though I only setState one of them

Viewed 63

Problem

using React, I have a meal, which has an array of ingredients

const [meal, setMeal] = useState()

    meal = {
      foo: ,
      bar: ,
      ingredients: [
        id:
        name:
      ]
    }

I also need to edit the ingredients name, so I have a different state to track it. I have used the spread operator on this.

[changeIngredients, setChangeIngredients] = useState();
// in a separate useEffect
setChangeIngredients([...meal.ingredients])

The problem starts when I update changeIngredients as such

  handleEdit = (e) => {
    let temp = [...changeIngredients];
    temp[e.positionOfArray].name = Number(e.target.value);
    setChangeIngredients(temp);
  };

I find that meal.ingredients is also updated, and as such can't do a comparison to see if anything changed.

I previously tried using setChangeIngredients with the response.data from an API call, but the results were the same.

setMeal(response.data)
setChangeIngredients([...response.data.ingredients])


Any advice or suggestions will be appreciated
2 Answers

That's because you are mutate on the same object, this setChangeIngredients([...meal.ingredients]) each object inside are still pointing to the same reference of ingredients

Bascially your need clone a copy of meal.ingredients first on your inital setChangeIngredients

const sourceArray = meal.ingredients;
const clonedArray = sourceArray.map(item => ({...item}));
setChangeIngredients(clonedArray)

For more info check here about immutable https://dev.to/antonio_pangall/best-practices-to-keep-objects-and-arrays-immutable-in-javascript-3nmm

As mentioned here, spread operator only makes a shallow copy. It only clones main object ... The copy of the properties will still be pass by reference.

Related