I recently started learning react and decided to create a Tic Tac Toe game, and I have encountered an issue where even after winning the game an extra move is required to log out winner. Here is the relevant code:
//TicTacToe.jsx
import { useState, useEffect } from "react";
import "../styles/board.css";
function TicTacToe() {
const [squares, setSquares] = useState(Array(9).fill(null));
const [isClicked, setIsClicked] = useState(Array(9).fill(false));
const [turnX, setTurnX] = useState(true);
const [winner, setWinner] = useState(null);
useEffect(() => {
if (winner !== null) {
if (winner) {
console.log("X is the winner");
} else {
console.log("O is the winner");
}
}
}, [winner]);
const checkWinner = () => {
if (winner !== null) return;
const winningCombinations = [
[0, 1, 2], // horizontal
[3, 4, 5],
[6, 7, 8],
[0, 3, 6], // vertical
[1, 4, 7],
[2, 5, 8],
[0, 4, 8], // diagonal
[2, 4, 6],
];
winningCombinations.forEach((combination) => {
const [a, b, c] = combination;
match(a, b, c);
});
};
const match = (a, b, c) => {
if (
squares[a] === squares[b] &&
squares[b] === squares[c] &&
squares[a] !== null
) {
if (squares[a] === "X") {
setWinner(true); // X winner
} else {
setWinner(false); // O winner
}
}
};
const handleClick = (index) => {
// don't make multiple click possible
if (isClicked[index]) return;
// do immutable updates
const newSquares = [...squares];
const newClicked = [...isClicked];
// print the click
newSquares[index] = printXO();
newClicked[index] = true;
// change state
setSquares(newSquares);
checkWinner(); // Check for a winner after updating the squares state
setTurnX(!turnX);
setIsClicked(newClicked);
};
const printXO = () => {
return turnX ? "X" : "O";
};
return (
<div>
<div className="board">
{squares.map((square, index) => (
// map the squares with div '_00' etc.
<div
className="square"
id={`_${Math.floor(index / 3)}${index % 3}`}
key={index}
onClick={() => handleClick(index)}
>
{square}
</div>
))}
</div>
</div>
);
}
export default TicTacToe;
/* board.css */
.board {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 10px;
width: 300px;
height: 300px;
margin: 0 auto;
background-color: #ddd;
}
.square {
display: flex;
align-items: center;
justify-content: center;
font-size: 48px;
background-color: #fff;
cursor: pointer;
}
.square:hover {
background-color: #f2f2f2;
}
The issue I'm facing is that the winner doesn't print when it is supposed to. After a winning move is made, the winner is only detected on the next move. It seems like there's a delay in updating the winner state.
Can someone please help me in identifying the problem?
Thanks in advance for your help!
PS: I know the game is incomplete, I'll complete it as soon as I fix this bug.