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
The solution for this turned out to be quite simple. Coming from a C# background I instinctively used the
var
keyword inside thefor
loop. In JS,var
is function-scoped so the value assigned toi
persisted outside of the loop which is why I believe I was seeing incorrect values from thereturn
statement. Changingvar
tolet
solved the problem:(I also changed
i < 10
toi < 9
since that was causing a different error.)I don’t think this loop will work like you intend.
For instance this conditional code:
Will run three times, when
i=0
,i=1
, andi=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.I think you need to use
useEffect
react hook to create theretVal
variable.And, I would like to know where did you declare the
handleClick()
function if you don’t mind.