Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
192 views
in Technique[技术] by (71.8m points)

javascript - Stop an update when a condition is met (React tic-tac-toe)

I'm creating a quick tic-tac-toe implementation in React, and ran into an issue, seen here: enter image description here

Here is the code:

https://codesandbox.io/s/cold-grass-yr6mn?file=/src/container/Board.jsx

The Problems:

1.) It prints the wrong winner (the game changes the turn after the user wins)

2.) When a user has won, I want to display "Winner: X", instead of "Next: X".

Why it's failing:

In my Board.jsx, I pass the following method down to my Square.jsx component, which updates the board state, and the player turn:

  const updateBoard = (squareIndex) => {
    setGameState((prevBoard) => {
      // handle previously set value
      if (prevBoard[squareIndex] !== "") {
        return prevBoard;
      }
      // otherwise update the board
      let updatedBoard = [...prevBoard];
      updatedBoard[squareIndex] = playerTurn;
      return updatedBoard;
    });

    // update player turn
    setPlayerTurn((turn) => (turn === "X" ? "O" : "X"));
  };

In the same file I have a useEffect that checks when the gameState or player turn update. This method determines the winner.

  // board update events/actions
  useEffect(() => {
    const isWinner = () => {
      const lines = [
        [0, 1, 2],
        [3, 4, 5],
        [6, 7, 8],
        [0, 3, 6],
        [1, 4, 7],
        [2, 5, 8],
        [0, 4, 8],
        [2, 4, 6],
      ];
      for (let i = 0; i < lines.length; i++) {
        const [a, b, c] = lines[i];
        if (
          gameState[a] &&
          gameState[a] === gameState[b] &&
          gameState[a] === gameState[c]
        ) {
          return true;
        }
      }
      return false;
    };

    if (isWinner()) {
      alert(`${playerTurn} is the winner.`);
      return;
    }
  }, [gameState, playerTurn]);

So the reason why it is printing the wrong winner is because once someone wins, it will still update the player turn, and then will display the losing player.

My Question

What is the best way to handle updating player turn? If I set the player in my useEffect, I will get an infinite render loop. I can think of some hacky ways to fix it like printing the opposite of whatever the current player turn is as the winner. But that does not seem ideal.

Any advice on the best way to approach this fix is appreciated.

Thanks!

question from:https://stackoverflow.com/questions/65557687/stop-an-update-when-a-condition-is-met-react-tic-tac-toe

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You can try this:

  • Add a state variable to maintain state. Initialize it as false
const [gameFinished, setFinished] = useState(false);
  • Add a prop to Square as disabled.
    1. Call callback on click based on this:
const clickHandler = () => {
  if (!isDisabled) updateBoard(boardPosition);
};
  1. Update className based on this
if (isDisabled) {
  classes.push("disabled");
}
  • Use newly create state variable to pass prop
isDisabled={gameFinished}

Sandbox link


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...