ReactJS - "Keys" error when adding components in loops
I was following the tutorial on how to build with React with the TIC TAC TOE example, and I found it very interesting.
At the end of the tutorial, I found one of the following challenges:
Rewrite Board to use two loops to make the squares instead of hard coding them.
This is the original render
method
render() {
return (
<div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
I first did it with just 1 loop and everything was working great
render() {
let col_count = 3;
let row_count = 3;
let rows = [];
for (var i = 0; i < row_count; i++) {
rows.push(
<div key={i} className="board-row">
{this.renderSquare(i*col_count + 0)}
{this.renderSquare(i*col_count + 1)}
{this.renderSquare(i*col_count + 2)}
</div>
);
}
return (
<div>{rows}</div>
);
}
But then I tried to code it with 2 loops:
render() {
let col_count = 3;
let row_count = 3;
let rows = [];
for (var i = 0; i < row_count; i++) {
let cols = [];
for (var j = 0; j < col_count; j++) {
cols.push(this.renderSquare(i*col_count + j));
}
rows.push(
<div key={i} className="board-row">{cols}</div>
);
}
return (
<div>{rows}</div>
);
}
And I started getting the famous "keys" error on the console:
Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of
Board
.
So now I wonder: What is that I am missing? The rows have still a valid key ID that was working when i was just using one loop. And the columns inside each row come from another render method that has always worked.
Where is the problem with my second implementation? How could I implement it so that I do not get that error?
Update:
In case needed, this is renderSquare
renderSquare(i) {
return (
<Square
value={this.props.squares[i]}
onClick={() => this.props.onClick(i)}
/>
);
}
I think your <Square />
components need keys.
renderSquare(i) {
return (
<Square
key={i}
value={this.props.squares[i]}
onClick={() => this.props.onClick(i)}
/>
);
}
I believe you're seeing the warning because in your 2nd implementation you also have the cols array which is basically a list of Square's. So your code is something like :
render() {
let col_count = 3;
let row_count = 3;
let rows = [];
for (var i = 0; i < row_count; i++) {
let cols = [];
for (var j = 0; j < col_count; j++) {
cols.push(this.renderSquare(i*col_count + j));
}
rows.push(
<div key={i} className="board-row">
<Square/> //needs key
<Square/> //needs key
</div>
);
}
return (
<div>{rows}</div>
);
}