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.