TheViralGriffin
TheViralGriffin

Reputation: 441

state gets updated before setState is called

lifeParser is a method called to process and update boardData. The problem is boardData gets updated while the loop is still processing.

lifeParser(){
    var parseArray = this.state.boardData.slice(0);

    for(var i=0;i<30;i++){
        for(var j=0;j<30;j++){
            parseArray[i][j] = 5; // boardData gets updated here before setState is even called
        }
    }
    this.setState({boardData : parseArray});
}

Upvotes: 3

Views: 72

Answers (2)

CodinCat
CodinCat

Reputation: 15914

Because it's a nested array. You are only copying the first level (shallow clone). The inner arrays are still the same references. Consider the follow example:

var nestedArray = [
 [1, 2, 3],
 [6, 6, 6, 6, 7, 8],
 [0, 3, 5, 6, 5]
];

// This only does a shallow clone
var copy = nestedArray.slice(0);

// When you do this
copy[0][0] = 100;

// `nestedArray` will also be mutated,
// you get 100 here
console.log(nestedArray[0][0]);

In your case, you can do a deep clone or simply use something like map() to get a fresh new array:

lifeParser(){
    var parseArray = this.state.boardData.slice(0);

    for (var i = 0; i < 30; i++) {
      parseArray[i] = parseArray[i].map(() => 5);
    }
    this.setState({boardData : parseArray});
}

Doing a deep clone in this example is more expensive because you need 1 more loop. The benefit of using map() here is that you compute and clone your data at the same time.

You can also use two map()s in this example:

lifeParser(){
    var parseArray = this.state.boardData.map(innerArray => innerArray.map(() => 5));
    this.setState({boardData : parseArray});
}

// Or this might be more readable:
var parseArray = this.state.boardData.map(innerArray => {
  return innerArray.map(() => 5);
});

Upvotes: 2

Tharaka Wijebandara
Tharaka Wijebandara

Reputation: 8065

This is because your boardData is multi-dimensional and you can't clone it only with slice method. Use it with map like this.

var parseArray = this.state.boardData.map(function(arr) {
    return arr.slice();
});

or with arrow syntax

var parseArray = this.state.boardData.map(a => a.slice());

Upvotes: 2

Related Questions