Array.push() overwrites pushed elements [Recipe Box Project]

On submit the _addRecipe function gets called add it will push the value of the input and the textarea into the old state-object. On the first execution the function pushs a ne array in the object, but the folloing calls just overwrite the new added array…

The whole code is on codepen

Here is the _addRecipe funtion:

_addRecipe(e, input, textarea) {
      this.setState({
        recipes: this.state.recipes.push({title: input, ingredients: setIngretients()})
      });
      console.log({title: input, ingredients: setIngretients()}, this.state.recipes);
      console.log(this.state.recipes);

      function setIngretients() {
        var ingredients = [];
        ingredients = textarea.split(',').map(function(ingredient) {
          return ingredient;
        });
        return ingredients;
      }
    }

push() doesn’t return the array you push to. You need to make a copy of the array and the pass that to setState().

_addRecipe(e, input, textarea) {
      let recipeCopy = this.state.recipes;
      recipeCopy.push({title: input, ingredients: setIngretients()});
      this.setState({
        recipes: recipeCopy
      });
      console.log({title: input, ingredients: setIngretients()}, this.state.recipes);
      console.log(this.state.recipes);

     
    }
1 Like

@PortableStick, this makes sense but it don’t works…

In JavaScript, complex data types are always passed by reference. What this mean is essentially this in a JavaScript console:

var a = {}; var b = a; a == b; => true
In JavaScript, an Array is actually an Object, so the same applies.

For an Array, the best approach to take to create an actual copy is this:

var myArray = [1, 2, 3]; var myCopiedArray = myArray.slice(); myArray == myCopiedArray; => false

The Array method slice() returns a copy of the array, rather than modifying the array directly. When working with React, this is nearly always what you want. So I’d suggest something like this:

let newState = this.state.recipes.slice(); newState.push({title: input, ingredients: setIngredients()}); this.setState({ recipes: newState });

There are several more concise ways of accomplishing this, but the above will get you started.

For more information on this topic, I’d Google around for “javascript and immutability”. Also you may want to look at the ES6 spread operator, which makes the above super easy, once you become comfortable with the syntax:

this.setState({ recipes: [...this.state.recipes, {title: input, ingredients: setIngredients()}] });

which works because:

[...myArrayCopy] == myArrayCopy; => false

But I digress.