I'm pretty proficient in JavaScript but learning React. I'm trying to make tic-tac-toe. When I get a winner, I want the this.state.message to update immediately, the this.state.done to change to true immediately, and the this.state.turn to not change. Currently I've figured out some of these but not the this.state.turn change. It says that the wrong player wins. I know that setState is asynchronous and that's why I'm having trouble updating these things together, and I fixed some of them with a callback, but I'm trying to find a better way and to generally understand everything better.
class Board extends Component {
constructor(props) {
super(props);
this.state = {
board: ['', '', '', '', '', '', '', '', ''],
turn: 'O',
message: 'O goes',
done: false
}
}
addItem(x) {
if (this.state.done === true) {
this.setState({message: this.state.turn + ' wins'});
return;
}
let array = [...this.state.board];
if (array[x] !== "") {
return;
}
array[x] = this.state.turn;
this.setState({board: array}, () => {
this.checkWinners(0, 1, 2);
this.checkWinners(3, 4, 5);
this.checkWinners(6, 7, 8);
this.checkWinners(0, 3, 6);
this.checkWinners(1, 4, 7);
this.checkWinners(2, 5, 8);
this.checkWinners(0, 4, 8);
this.checkWinners(2, 4, 6);
if (this.state.done === false) {
this.setState({turn: (this.state.turn === "X") ? "O" : "X"});
this.setState({message: (this.state.message === "X goes") ? "O goes" : "X goes"});
}
});
}
checkWinners(a, b, c) {
if ((this.state.board[a] === "X"
&&
this.state.board[b] === "X"
&&
this.state.board[c] === "X")
||
(this.state.board[a] === "O"
&&
this.state.board[b] === "O"
&&
this.state.board[c] === "O"
)
) {
this.setState({done: true}, () => {
console.log('Winner');
this.setState({message: this.state.turn + ' wins'});
});
}
}
render() {
return (
<>
<h1>Tic-Tac-Toe</h1>
<h2>{this.state.message}</h2>
<div className="board">
{this.state.board.map((item, index) => (
<div className="boxes" key={index} onClick={() => this.addItem(index)}>{this.state.board[index]}</div>
))}
</div>
</>
)
}
}