I’m working through the Lists and Keys section of the React tutorial.
I’ve created a component, Board
(code below), which draws a tic-tac-toe board made up of buttons contained in Square
(code omitted) components. The Square
components are items in row arrays which are themselves items in a board array to form a grid made up of nested arrays.
I have a question about the following paragraph from the tutorial.
Extracting Components with Keys
Keys only make sense in the context of the surrounding array. For example, if you extract aListItem
component, you should keep the key on the<ListItem />
elements in the array rather than on the<li>
element in theListItem
itself.
In my code below, I have a method, renderSquare
, which returns individual elements in the form of Square
components. These elements are stored in an array, so they need a key
prop for React to work its rendering magic. Because renderSquare
is an unbound old-style function/method, I think it takes on the execution context of gridBuilder
, so there’s no problem with assigning the key within the renderSquare
method. However, I’m not sure if using an arrow function for renderSquare
would break the key
rule I quoted above.
Can anyone tell me if I’m understanding the tutorial correctly in regards to the key
prop? Do list-item factories like renderSquare
break how array keys work in React? Does the key absolutely need to be assigned where the list is being created, or are there exceptions?
class Board extends React.Component {
renderSquare(i) {
return (
<Square
key={"square"+i}
value={this.props.squares[i]}
onClick={() => this.props.onClick(i)}
/>
);
}
// replaced hard-coded grid with loop
gridBuilder() {
let gridElems = [];
let rowElems = [];
for (let i = 0; i < 9; i++) {
// is it a problem if renderSquare key assignment
// doesn't happen in the gridBuilder context?
let elem = (this.renderSquare(i));
rowElems.push(elem);
if ((i + 1) % 3 === 0) {
let row = (
<div className="board-row" key={"row" + ((i+1)/3)}>
{rowElems}
</div>);
gridElems.push(row);
rowElems = [];
}
}
return <div>{gridElems}</div>
}
render () {
return (
this.gridBuilder()
);
}
}