Within handleClick
function, after I click a cell, squares
state gets updated through setSquares(copiedSquares)
then I console.log squares
to see if state has been updated properly. Strange thing is after my first click in the cell, I see the 'X' shows up in the cell as expected, but console.logging square state shows still empty! But UI is based on squares
state so this is confusing to me. After I click for 2nd time in different cell then state squares
shows previous state so it's one step behind. So getWinner()
function is not working properly due to this behaviour. Can anybody explain why this is happening?
https://codesandbox.io/s/tic-tac-toe-practice-kvun2d?file=/src/App.js:0-1709
import "./styles.css";
import React, { useState } from "react";
export default function Game() {
const [squares, setSquares] = useState(Array(9).fill(""));
const [playerTurn, setPlayerTurn] = useState("X");
const [winner, setWinner] = useState("");
let winningCondition = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8]
];
const getWinner = () => {
winningCondition.forEach((arr) => {
if (
squares[arr[0]] === "" ||
squares[arr[1]] === "" ||
squares[arr[2]] === ""
) {
return;
} else if (
squares[arr[0]] === squares[arr[1]] &&
squares[arr[1]] === squares[arr[2]]
) {
setWinner(squares[arr[0]]);
console.log("You Win!");
}
});
};
const handleClick = (idx) => {
let copiedSquares = [...squares];
if (playerTurn === "X") {
copiedSquares[idx] = "X";
setPlayerTurn("O");
} else {
copiedSquares[idx] = "O";
setPlayerTurn("X");
}
setSquares(copiedSquares);
console.log(squares); // array is empty!
getWinner();
};
function Square({ idx }) {
return <td onClick={() => handleClick(idx)}>{squares[idx]}</td>;
}
return (
<table>
<tbody>
<tr>
<Square idx={0}></Square>
<Square idx={1}></Square>
<Square idx={2}></Square>
</tr>
<tr>
<Square idx={3}></Square>
<Square idx={4}></Square>
<Square idx={5}></Square>
</tr>
<tr>
<Square idx={6}></Square>
<Square idx={7}></Square>
<Square idx={8}></Square>
</tr>
{winner && <p>Winner is {winner}</p>}
</tbody>
</table>
);
}
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
table {
border-collapse: collapse;
width: 200px;
height: 200px;
}
td,
th {
border: 1px solid black;
text-align: left;
padding: 8px;
}