我正在学习 React 并开发 John Conway 的 Game of Life 应用。我在状态/构造函数中定义了一个二维数组,它创建了一个游戏方 block 板。我有一个名为 isSquareAlive 的函数,它处理网格中的特定方 block 在生命游戏意义上是否“活着”,并更新方 block 并将它们设置为在用户单击它们时活着。我还有另一个名为 selectBoardSize
的函数,它允许用户单击按钮并调整板的大小。
当应用程序安装时,我会生成一个随机板,其中填充了一些设置为“事件”的方 block ,而另一些则没有。我在 componentDidMount
中处理这个问题:
componentDidMount = () => {
const data = this.state.board;
// Creates random decimal number between 0 and 1
const startingBoard = data.map(a => a.map(Math.random));
// Rounds decimal numbers to either 0 or 1 so the grid can display whether the cell is alive or dead
const rounded = startingBoard.map(a => a.map(Math.round));
this.setState({
board: rounded
});
}
这很好用。如果用户尝试通过 selectBoardSize 调整板的大小,我想更改板的大小,然后再次用随机的“事件”单元格填充它。这是selectBoardSize
:
// Allows user to click button and change size of game board
selectBoardSize = (width, height) => {
this.setState({
boardHeight: height,
boardWidth: width,
board: Array(this.state.boardHeight).fill(0).map(_ =>
Array(this.state.boardWidth).fill(0))
});
{/*this.onChangeBoardSize(width, height);*/}
}
当用户更改板尺寸时,我尝试使用 componentDidUpdate
获取新的板尺寸并用该板尺寸的随机“事件”单元格填充它,就像我最初使用 componentDidMount
。这就是我遇到困难的地方。
这是我的componentDidUpdate
:
// Attempts to fill board with random alive squares when user resizes the size of the board via onClick/selectBoardSize()
componentDidUpdate = (prevProps, prevState) => {
console.log('PrevState is : ' + prevProps, prevState);
// Attempts to update board height and width and then populate board with random "alive" squares
if(this.state.boardWidth !== prevState.boardWidth) {
if(this.state.boardHeight !== prevState.boardHeight) {
// Console.log runs, if statements equate to true when user resizes board
console.log('Nested if statements in componentDidUpdate triggered');
const boardWidth = this.state.boardWidth;
const boardHeight = this.state.boardHeight;
const data = this.state.board;
// Creates random decimal number between 0 and 1
const startingBoard = data.map(a => a.map(Math.random));
// Rounds decimal numbers to either 0 or 1 so the grid can display whether the cell is alive or dead
const rounded = startingBoard.map(a => a.map(Math.round));
this.setState({
boardWidth: boardWidth,
boardHeight: boardHeight,
board: rounded
})
}
}
}
当用户单击按钮调整大小时,板成功更改尺寸,但它不会像应有的那样生成随机“事件”方 block 。它只是改变了棋盘的高度和宽度,但棋盘是空的。
如何使用 componentDidUpdate
在调整大小时用随机“事件”单元填充游戏板(与最初安装时的操作类似,但在板改变大小时适当调整大小)。 componentDidUpdate
是正确的方法吗?这是 setState 异步的问题吗?
很确定我想得太多了。
您可以查看 codesandbox 上的代码。
最佳答案
您不需要为此使用 componentDidUpdate
,稍后会详细介绍。
这不起作用,因为您(顺便说一下,正确地)将 componentDidMount
代码包装到两个条件中,以检查 boardWidth
和 boardHeight 是否有效
确实改变了。问题是,高度永远不会改变,因此它永远不会到达代码的那部分。
无论哪种方式,如果您仔细查看代码,就会发现您在不必要的情况下更新了太多次状态。如果您事先已经知道用户想要的板尺寸,请一次性完成所有操作。
据我所知,每次用户更改大小时您都想要执行以下操作:
- 根据所需的宽度和高度创建一个新板;
- 用随机的事件方 block 填充它;
您只需要 onChangeBoardSize
函数,并进行微小的更改。
请注意,您不需要从状态中检索板,因为旧的宽度和高度将使其过时;
onChangeBoardSize = (width, height) => {
// Recreate board with new width and height values
const data = Array(height)
.fill(0)
.map(_ => Array(width).fill(0));
// Creates random decimal number between 0 and 1
const startingBoard = data.map(a => a.map(Math.random));
// Rounds decimal numbers to either 0 or 1 so the grid can display whether the cell is alive or dead
const rounded = startingBoard.map(a => a.map(Math.round));
this.setState({
boardHeight: height,
boardWidth: width,
board: rounded
});
};
提示:请注意过多的后续状态修改。总是更喜欢一次性完成所有操作,而不是顺序触发 setState。特别是在 React 生命周期方法中
关于javascript - React - 使用 componentDidUpdate 根据从另一个函数传递的数据更新状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52487585/