Build a Tic-Tac-Toe Game - Build a Tic-Tac-Toe Game

Tell us what’s happening:

I can’t pass tests 6 to 11, after clicking the reset button sometimes a message of potential loop appears, and after clicking the reset and then the button.square one of the buttons disappears. I wrote all the code in vscode, using vite, and everything works fine.

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <title>Tic-Tac-Toe</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.development.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.development.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.26.5/babel.min.js"></script>
    <script
      data-plugins="transform-modules-umd"
      type="text/babel"
      src="index.jsx"
    ></script>
    <link rel="stylesheet" href="styles.css" />
</head>

<body>
    <div id="root"></div>
    <script
      data-plugins="transform-modules-umd"
      type="text/babel"
      data-presets="react"
      data-type="module"
    >
      import { Board } from './index.jsx';
      ReactDOM.createRoot(document.getElementById('root')).render(<Board />);
    </script>
</body>

</html>
/* file: index.jsx */
const { useState, useEffect, useMemo } = React;

const squareInitialValues = {
  a1: "",
  b1: "",
  c1: "",
  a2: "",
  b2: "",
  c2: "",
  a3: "",
  b3: "",
  c3: "",
};

const patterns = [
  ["a1", "b1", "c1"], //Horizontal
  ["a2", "b2", "c2"], //Horizontal
  ["a3", "b3", "c3"], //Horizontal
  ["a1", "a2", "a3"], //Vertical
  ["b1", "b2", "b3"], //Vertical
  ["c1", "c2", "c3"], //Vertical
  ["a1", "b2", "c3"], //Diagonal
  ["c1", "b2", "a3"], //Diagonal
];

export function Board() {
  const [isPlayer, setIsPlayer] = useState(false);
  const [player, setPlayer] = useState("");
  const [message, setMessage] = useState("");
  const [squareValues, setSquareValues] = useState(squareInitialValues);
  const [validPatterns, setValidPatterns] = useState([]);
  const [clicks, setClicks] = useState(0);
  const [winner, setWinner] = useState("");
  const [disableSquareBtns, setDisableSquareBtns] = useState(false);

  const boardCoordinates = useMemo(() => Object.keys(squareValues), [setSquareValues]);
  const messagesList = useMemo(
    () => ({
      next: `Next player: ${player}`,
      winner: `The Winner is: ${winner}`,
      tie: `It's a Draw!`,
    }),
    [player, winner],
  );

  useEffect(() => {
    setPlayer(!isPlayer ? "X" : "O");
  }, [isPlayer]);

  useEffect(() => {
    if (checkPatterns()) setWinner(player);
  }, [validPatterns]);

  useEffect(() => {
    if (winner) setDisableSquareBtns(true);
  }, [winner]);

  useEffect(() => {
    if (clicks === 9 && winner === "") {
      setMessage(messagesList["tie"]);
    } else if (winner) {
      setMessage(messagesList["winner"]);
    } else {
      setMessage(messagesList["next"]);
    }
  });

  const handleClick = (e) => {
    const squareId = e.target.id;

    if (squareValues[squareId] === "") {
      setSquareValues((prevState) => ({
        ...prevState,
        [squareId]: player,
      }));
      setIsPlayer((prevState) => !prevState);
      setValidPatterns(patterns.filter((pattern) => pattern.includes(squareId)));
      setClicks((prev) => prev + 1);
    }
  };

  const handleReset = () => {
    setIsPlayer(false);
    setSquareValues(squareInitialValues);
    setWinner("");
    setClicks(0);
    setDisableSquareBtns(false);
  };

  const checkPatterns = () => {
    return validPatterns.some((pattern) => {
      const refValue = squareValues[pattern[0]];

      return pattern.every((coordinate) => squareValues[coordinate] === refValue);
    });
  };

  return (
    <div className="board-container">
      {/* <p className="board-container__message">{winner ? `The Winner is: ${winner}` : `Next player: ${player}`}</p> */}
      <p className="board-container__message">{message}</p>

      <div className="board-container__grid">
        {boardCoordinates.map((coordinate) => (
          <SquareButton
            id={coordinate}
            key={coordinate}
            squareValue={squareValues[coordinate]}
            onClick={handleClick}
            disableSquareBtns={disableSquareBtns}
          />
        ))}
      </div>

      <button id="reset" className="btn btn--reset" onClick={handleReset}>
        Reset Game
      </button>
    </div>
  );
}

const SquareButton = ({ id, squareValue, onClick, disableSquareBtns }) => {
  return (
    <button id={id} className="square" onClick={onClick} disabled={squareValue || disableSquareBtns}>
      {squareValue}
    </button>
  );
};
/* file: styles.css */
.board-container {
  max-width: 20rem;

  margin-inline: auto;
}

.board-container__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: .5rem;
}

.square {
  aspect-ratio: 1;
}

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36

Challenge Information:

Build a Tic-Tac-Toe Game - Build a Tic-Tac-Toe Game