React tic tac toe handleClick

React tic tac toe handleClick
0

#1

I’ve been working through the tutorial on Reactjs.org . I don’t understand why the handleClick method stops the app updating once a winner is declared but only ignores the click if the square is already filled. Here is the function:

  handleClick(i) {
    const squares = this.state.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }

#2

It’s not clear which part baffles you. If the square is set or the game has been won, there’s nothing left to be done by the function, so it exits prematurely. Say you wanted to add an annoying beep if a player clicked on a full square, you’d move the second check to an individual if block and first make the sound before again returning prematurely — not allowing rewriting the position.


#3

What I don’t understand is why it still allows you to play if you click on a square that’s filled but stops play completely if a winner is declared, seeing as both checks exist in the same if statement.


#4

It does not let you play that square if the square is already filled. It checks two different things in the same if statement because of the || operator. The || means OR.


#5

Thanks, I do understand this part. I’ll try and rephrase again. How come when the function exits prematurely when the calculateWinner function returns something, no further clicks can be made, but when a player clicks on a square which is filled it exits (based on the same return statement) but allows further play once you click on an empty square.
In other words, why does the same return statement seem to yield slightly different results?


#6

can you share the full code on maybe a codepen.io so I can see it


#7

calculateWinner returns one of three values (‘X’, ‘O’, or null). When handleClick is called and passed the argument i (representing an index of the squares array), calculateWinner will return ‘X’ if three squares contain ‘X’ based on one of the 8 possible winning lines or ‘O’ if three square contain ‘O’ based on one of the 8 possible winning lines. Otherwise, it returns null.

When you have an if statement with two conditions separated by the || operator, then the if statement will evaluate to true even if only one of the conditions evaluates to true, which causes the if statement code block to execute. In this case, the if statement code block is a return statement which exits out of the handleclick function.

When a click is made on ANY square and the calculateWinner function returns an ‘X’ or ‘O’ (meaning either X or O had a winning line), the if statement evaluates to true, so the return statement exists the function (seemingly stopping the game). Let’s say that after a click on any given square, calculateWinner returns null. A null value is “falsy”, so the second if condition is evaluated. Suppose this click is made on a square which already contains an ‘X’ or ‘O’, that means squares[i] will be an ‘X’ or an ‘O’. Since non-empty strings are “truthy”, the 2nd if condition would evaluate to true causing the if statement to evaluate to true and hence execute the return statement.

If any of the “truthy” or “falsy” parts of my explanation are confusing, refer to the Falsy Bouncer challenge.


#8

#9

The reason you have two different results is because you are using a conditional statement meaning if the first statement is not true you move to the next step, but if you want to keep playing after the winner was announced then you need to loop though the condition of if.


#10

Thanks, I think I understand now. Because once the calculateWinner function evaluates as true, it cannot go back to returning null, so the if statement will always return true, thus seeming to stop play.