React-生命游戏-根据用户单击的元素来更新2D数组中特定元素的状态

时间:2018-09-21 19:21:38

标签: javascript reactjs multidimensional-array immutability setstate

我仍在学习React并致力于编写John Conway的《生活游戏》。我使用状态为2D的数组为游戏创建了一个游戏板。我将此二维数组存储在App.js中的状态中。我还有两个功能组件,Gameboard.jsSquare.js接收道具并创建游戏板。

Gameboard.js创建一个表格并将道具传递给Square.js,让它知道哪些正方形应该突出显示,哪些不应该突出显示。换句话说,它使每个单独的方块都知道用户是否单击了它,以及它是否在“生命游戏”意义上是“活跃的”。

用户单击Square.js中的特定正方形后,我有一个回调函数触发了onClick。回调函数aliveCallback,将被单击的特定正方形的X和Y坐标传递回App.jsApp.js触发一个名为alive的函数。

调用alive时,我需要更新2D数组的状态,以使特定的正方形(它是X和Y坐标,例如[0,0]或[0,1]等)。 )设置为存储在状态中的布尔值。然后,该布尔值可以作为Gameboard.js传递给isAlive。然后,游戏板将isAlive的值传递给Square.js,并且Square.js进行条件渲染,告知各个正方形以浅蓝色突出显示。

这真是令人难以置信,check out the Codesandbox and see the structure of the project可能最简单。提及我正在遵循SO海报在this post中给我的建议也有帮助。

阅读并查看React文档后,看来解决此问题的一种好方法是使用immutability-helper及其update函数。这就是我采用的方法,但是我似乎无法使用X和Y坐标正确地更新所单击的特定正方形的状态。

与其在此处发布代码,不如在CodeSandbox上签出代码可能更容易,更整洁。如何编写我的alive函数,以便它正确更新所单击的正方形的状态?

这是我尝试过的:

alive = (x, y) => {
    console.log(x, y);

    const data = this.state.board;
    const ySquare = y;
    const xSquare = x;
    console.log("X square is : " + xSquare);
    console.log("Y square is : " + ySquare);

    const updateData = update(data, {
      xSquare: {$set: this.setState({ alive: !this.state.alive })}
    });

  }

这里的逻辑是尝试将xSquare和ySquare传递给update,然后尝试为该特定正方形将live设置为true。

1 个答案:

答案 0 :(得分:0)

我认为问题在于您在App上有一个状态变量alive,对于每个电池的寿命状态都感到困惑。

我做了一些重做,我的解决方案不使用update from 'immutability-helper',因为我不熟悉它,但是我认为解决方案中的逻辑非常简单。

这里是App.alive

alive = (x, y) => {
  console.log(x, y);

  const data = this.state.board;
  const ySquare = y;
  const xSquare = x;
  console.log("X square is : " + xSquare);
  console.log("Y square is : " + ySquare);

  const newData = data.map((row, y) => {
    return y === ySquare ? (
      row.map((cell, x) => x === xSquare ? 1 : cell)
    ) : (
      row
    )
  })

  this.setState({ board: newData });
}

基本上newData来自检查板上的每个单元格,如果当前单元格的坐标匹配xSquare, ySquare,它将单元格的值设置为1,否则保持不变。

作为补充说明,我建议将此方法重命名为makeCellAlive之类的名称,以更清楚地表明它是一种可以执行某些操作的方法。

修改

如果您想单击鼠标以根据其当前状态使该单元处于活动状态或死亡状态,则可以更改该行:

row.map((cell, x) => x === xSquare ? 1 : cell)

row.map((cell, x) => x === xSquare ? (cell + 1) % 2 : cell)

看起来像一个很棒的应用。