skip to Main Content

I’m new to React and am playing around with their Tic-Tac-Toe tutorial. I wanted to try generating the Squares using a for-loop but am running into an issue that I’m not quite understanding. That part of my code (placed at the bottom of the Board function) looks like this:

   const retVal = Array(3).fill(null);
    for (var i = 0; i < 10; i += 3) {
        if (i < 3) {
            retVal[0] = (
                <>
                    <Square value={squares[i]} onSquareClick={() => handleClick(i)} />
                    <Square value={squares[i + 1]} onSquareClick={() => handleClick(i + 1)} />
                    <Square value={squares[i + 2]} onSquareClick={() => handleClick(i + 2)} />
                </>
            );
        }
        else if (i >= 3 && i < 6) {
            retVal[1] = (
                <>
                    <Square value={squares[i]} onSquareClick={() => handleClick(i)} />
                    <Square value={squares[i + 1]} onSquareClick={() => handleClick(i + 1)} />
                    <Square value={squares[i + 2]} onSquareClick={() => handleClick(i + 2)} />
                </>
            );
        }
        else {
            retVal[2] = (
                <>
                    <Square value={squares[i]} onSquareClick={() => handleClick(i)} />
                    <Square value={squares[i + 1]} onSquareClick={() => handleClick(i + 1)} />
                    <Square value={squares[i + 2]} onSquareClick={() => handleClick(i + 2)} />
                </>
            );
        }
    }

    return (
        <>
            <div className="status">{status}</div>
            <div className="board-row">
                {retVal[0]}
            </div>
            <div className="board-row">
                {retVal[1]}
            </div>
            <div className="board-row">
                {retVal[2]}
            </div>
        </>
    );

I realize this may not be the most elegant solution for generating the squares (and the tutorial mentions using two loops for this without showing an example) but that’s a secondary question. The issue is that when handleClick(i) gets called the value of i received by this event handler is not what I was expecting. For example, when clicking the first square the value received for i is 12 and not 0. Subsequently, all the other squares also have unexpected i values. I’ve verified that i is 0 when retVal[0] is created so this appears to have something to do with how React renders the output since i is being set to a value outside the range of the for-loop. Trying to understand why (or figure out if I’m missing an obvious bug.)

3

Answers


  1. Chosen as BEST ANSWER

    The solution for this turned out to be quite simple. Coming from a C# background I instinctively used the var keyword inside the for loop. In JS, var is function-scoped so the value assigned to i persisted outside of the loop which is why I believe I was seeing incorrect values from the return statement. Changing var to let solved the problem:

    for (let i = 0; i < 9; i += 3) { ... }
    

    (I also changed i < 10 to i < 9 since that was causing a different error.)


  2. I don’t think this loop will work like you intend.

    For instance this conditional code:

          if (i < 3) {
                retVal[0] = (
                    <>
                        <Square value={squares[i]} onSquareClick={() => handleClick(i)} />
                        <Square value={squares[i + 1]} onSquareClick={() => handleClick(i + 1)} />
                        <Square value={squares[i + 2]} onSquareClick={() => handleClick(i + 2)} />
                    </>
                );
            }
    

    Will run three times, when i=0, i=1, and i=2. So your top row (retVal[0]) will end up with the third (i=2) version because it will override the Squares you created the first two times.

    Login or Signup to reply.
  3. I think you need to use useEffect react hook to create the retVal variable.

    And, I would like to know where did you declare the handleClick() function if you don’t mind.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search