0

The code below is not running as I expect it to, how come that the console.log() (at the //THIS) is affected by the code after it? If i run the following code with the outcommented code, the results of the top loggings change. Opposed to running it without the outcommented code so it doesnt change.

some more info about the code below, next.shape[0] returns a double array that looks like this:

[0,0,0,0],
[0,0,0,0],
[0,0,1,0],
[1,1,1,0]

the state.array is also a double array of objects that's about 20x10. (As you might've guessed, I'm trying to build tetris). I'm trying to copy the shape in the above array into the this.state.array, so i created an tempField array so i can edit it and then paste it into the setState().

console.log(this.state.nextShape.shape[0]) 
var tempField = this.state.array.slice(0);
console.log("state array before: ")
console.log(this.state.array) // THIS

console.log("temp Field before: ")
console.log(tempField)// and THIS
// var tempPosition = this.state.currentPosition.slice(0);
// let z = 0;// for (let y = 0; y < this.state.nextShape.shape[0].length; y++) {
//     for (let x = 0; x < this.state.nextShape.shape[0][y].length; x++) {
//         if (this.state.nextShape.shape[0][y][x] == 1) {
//             tempField[y][x + 3] = { occupied: false, color: this.state.nextShape.color };
//             tempPosition[z] = [y, x + 3]
//             z++;
//             console.log(z)
//         }
//     }
// }
// console.log("temp Field after: ")
// console.log(tempField)
// this.setState({ array: tempField });
// this.setState({ currentPosition: tempPosition });
// this.setState((state, props) => ({ currentShape: state.nextShape },
//     function () {
//         this.setState({ nextShape: BlockTypes[Math.floor(Math.random() * BlockTypes.length)] });
//     }));

In simpler terms how come a metaphorical piece of code like this:

var numberA = 0;
console.log(numberA);
numberA =+ 100;
console.log(numberA);

In my case (the first block of code), both return the same answer? And how do I fix it?

2 Answers2

1

This is how mutability works in javascript, when you mutate an object (and arrays are objects), this is reflected every where in the code, even for previous log statements - actually i think chrome dev tools shows a note about this that it is might be showing newer snapshots.

Your code if stripped out of details is something like this

const array = [0,1]
console.log(array)
array[0] = 1

// now if you go back to the previous log statement you will see that the first element is 1, even though the log statement is before
// if you want to make sure that in a log statement you are seeing the object before further mutations, then clone it

// one way of cloning and will not work with circular objects (extremely slow, but just so you can see where in your code mutations are happening)
const array = [0,1]
console.log(JSON.parse(JSON.stringify(array))) // you will still see the zero here
array[0] = 1
 
ehab
  • 7,162
  • 1
  • 25
  • 30
0

I think what @ehab is saying is correct, but to expand on that and apply it more directly to your code, when you call

var tempField = this.state.array.slice(0);

tempField is a new array, but the arrays inside it are not, they are references to the same sub-arrays that are in state.

In the for loop when you set

tempField[y][x + 3] = { occupied: false, color: this.state.nextShape.color };

you are mutating the existing sub-arrays of tempField, and also state.

It's fine to mutate tempField, after all that's why you create it in the first place so you can mutate it instead of state. But in doing so, what you see in console.log is affected by the later code. And aside from that, mutating state should be avoided. One way to do that would be:

if (this.state.nextShape.shape[0][y][x] == 1) {
  let newRow = [...tempField[y]];
  newRow[x + 3] = { occupied: false, color: this.state.nextShape.color };
  tempField[y] = newRow; // this mutates tempField but not state
  tempPosition[z] = [y, x + 3];
  z++;
  ...

EvanMorrison
  • 1,212
  • 8
  • 13