DEV Community

Kuldeep Bora
Kuldeep Bora

Posted on

React's Tic-Tac-Toe using React Hooks

Hello All,
As I am learning react hooks, this is my take in changing react's tic-tac-toe game code to use hooks.

I will jump straight to code as the documentation in reactjs.org is one of the best I've ever seen. https://reactjs.org/tutorial/tutorial.html#what-are-we-building

Functions remains same as their class counterpart:

Square(props), Board(props) and calculateWinner(squares)

The "Game" component is changed to functional component and is using hooks now.


const Game = () => {
      const [history,setHistory] = React.useState([{ squares: Array(9).fill(null) }]);
      const [stepNumber, setStepNumber] = React.useState(0);
      const [xIsNext, setXIsNext] = React.useState(true);
      const [status, setStatus] = React.useState("");

      const handleClick = (i) => {
        const hist = history.slice(0, stepNumber + 1);
        const current = hist[hist.length - 1];
        const squares = current.squares.slice();
        if (calculateWinner(squares) || squares[i]) {
          return;
        }
        squares[i] = xIsNext ? "X" : "O";

        setHistory(hist.concat([{ squares }]));
        setStepNumber(hist.length);
        setXIsNext(!xIsNext);
      }

      const jumpTo = (step) => {
        setStepNumber(step);
        setXIsNext((step % 2) === 0);
      }


      const moves = history.map((step, move) => {
        const desc = move ?
          'Go to move #' + move :
          'Go to game start';
        return (
          <li key={move}>
            <button onClick={() => jumpTo(move)}>{desc}</button>
          </li>
        );
      });

      let current = history[stepNumber]; 
      let winner = 0; 
      React.useEffect(()=> {
        current = history[stepNumber];
        winner = calculateWinner(current.squares);    

        if (winner) {
          setStatus("Winner: " + winner);
        } else {
          setStatus("Next player: " + (xIsNext ? "X" : "O"));
        }

      });

      return (
        <div className="game">
          <div className="game-board">
            <Board
              squares={current.squares}
              onClick={i => handleClick(i)}
            />
          </div>
          <div className="game-info">
            <div>{status}</div>
            <ol>{moves}</ol>
          </div>
        </div>
      );

    }

I am updating the status and calculating the winner in a useEffect hook as this will be called at every render (update).

The working code: https://codepen.io/kuldeep-bora/pen/QWbWPrY

Top comments (0)