I'm learning React and working on a John Conway's Game of Life app. I have a 2D array defined in the state/the constructor which creates a game board of squares. I have a function called isSquareAlive
that handles whether or not a particular square in the grid is "alive" in the Game of Life sense and updates squares and sets them to being alive if the user clicks on them. I also have another function called selectBoardSize
which allows the user to click a button and adjust the size of the board.
When the App mounts I generate a random board filled with some squares set to "alive" and some not. I take care of this inside 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
});
}
This works fine. If the user attempts to adjust the size of the board via selectBoardSize
I want to change the size of the board and then again fill it with random "alive" cells. Here is 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);*/}
}
When the user changes the board size I am attempting to use componentDidUpdate
to grab the new board size and fill it with random "alive" cells for that board dimension, much like I do initially with componentDidMount
. This is where I am having difficulty.
Here's my 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
})
}
}
}
The board successfully changes dimensions when the user clicks the buttons to resize it, but it does not generate random "alive" squares like it should. It just changes the height and width of the board but the board is empty.
How can I use componentDidUpdate
to fill the game board with random "alive" cells when it is resized (similar to what it does when initially mounting, but sized appropriately when the board changes sizes). Is componentDidUpdate
the correct approach? Is this an issue with setState being asynchronous?
Pretty sure I am overthinking this.
You can check out the code on codesandbox.