【问题标题】:ReactJS question about arrays in state and the async of itReactJS 关于状态数组及其异步的问题
【发布时间】:2020-11-08 18:37:44
【问题描述】:

下面的代码没有按照我的预期运行,console.log()(在//THIS处)怎么会受到代码的影响之后呢?如果我使用注释掉的代码运行以下代码,则顶部日志记录的结​​果会发生变化。反对在没有注释代码的情况下运行它,因此它不会改变。

关于下面代码的更多信息,next.shape[0] 返回一个看起来像这样的双精度数组:

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

state.array 也是一个大小约为 20x10 的双对象数组。 (你可能已经猜到了,我正在尝试构建俄罗斯方块)。我正在尝试将上述数组中的形状复制到 this.state.array 中,所以我创建了一个 tempField 数组,以便我可以对其进行编辑,然后将其粘贴到 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)] });
//     }));

简单来说,这样一段隐喻的代码是怎么来的:

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

就我而言(第一段代码),两者都返回相同的答案?我该如何解决?

【问题讨论】:

标签: javascript arrays reactjs asynchronous state


【解决方案1】:

这就是可变性在 javascript 中的工作方式,当你改变一个对象(数组是对象)时,这反映在代码中的每一个地方,即使是以前的日志语句 - 实际上我认为 chrome 开发工具显示了一个关于这个的注释它可能会显示较新的快照。

如果去掉细节,你的代码是这样的

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
 

【讨论】:

    【解决方案2】:

    我认为@ehab 的说法是正确的,但是当您调用时,要对此进行扩展并将其更直接地应用到您的代码中

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

    tempField 是一个新数组,但其中的数组不是,它们是对处于状态的相同子数组的引用。

    在for循环中设置时

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

    您正在改变 tempField 的现有子数组以及状态。

    改变 tempField 很好,毕竟这就是你首先创建它的原因,这样你就可以改变它而不是状态。但这样做时,您在 console.log 中看到的内容会受到后面代码的影响。除此之外,应该避免突变状态。一种方法是:

    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++;
      ...
    
    

    【讨论】:

      猜你喜欢
      • 2014-09-23
      • 2019-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-13
      • 2016-02-26
      • 2020-01-09
      相关资源
      最近更新 更多