Reputation: 25
Im new to react so im not sure whats going wrong here... Im trying to create a 3x3 structure of input boxes. This is what i came up with
function Square(prop){
return (<input type = 'text' class='w-25' style="display:inline-block">${prop.key}</input>);
}
function Row(props){
const row =[];
for( let i=props.key*3;i<(props.key+3);i++){
row.push(<Square key ={i}/>);
}
return (row);
}
class Box extends React.Component{
constructor(props){
super(props);
this.state = {
squares: Array(9).fill(null),
xIsNext: true,
};
}
render(){
let board =[];
for( let i=0; i<3;i++){
board.push(<div><Row key={i} /></div>);
}
return (board);
}
}
ReactDOM.render(
<Box />,
document.getElementById('root')
);
But I am getting the error
Warning: Each child in an array or iterator should have a unique "key" prop.
As far as my Dom goes the 3 rows have been rendered as
Any help would be greatly appreciated
UPDATE
After trying out some answers given below I've ended up with a single row of 4 input boxes... although I've only specified 3 in the loop. Why is this can some one explain and I've specified 2 more rows.This is the new code
function Square(prop){
return (<input type = 'text' id={prop.value} value={'x'}></input>);
}
function Row(props){
const row =[];
for( let i=props.value*3;i<(props.value+3);i++){
const val = `${i}input`;
const key = `${i}square`;
row.push(<Square key ={key} value={val}/>);
}
return (row);
}
class Box extends React.Component{
constructor(props){
super(props);
this.state = {
squares: Array(9).fill(null),
xIsNext: true,
};
}
render(){
let board =[];
for( let i=0; i<3;i++){
const key = `${i}row`;
board.push( <Row key={key} value={i}/>);
console.log(i)
}
return (board);
}
}
ReactDOM.render(
<Box />,
document.getElementById('root')
);
Upvotes: 0
Views: 101
Reputation: 10621
The key prop should be on the first element of the iteration which is the div
element:
board.push(<div key={i}><Row /></div>);
Also note that this row for( let i=props.key*3;i<(props.key+3);i++)
might not work for you as there is not more key prop.
You can change it to: for( let i=0;i<3;i++)
Notice that it is an Anti-Pattern to use index as a key.
a key is the only thing React uses to identify DOM elements. What happens if you push an item to the list or remove something in the middle? If the key is same as before React assumes that the DOM element represents the same component as before. But that is no longer true.
Took from This medium - Index as a key is an anti-pattern
EDIT:
Added a sample code that should run for you.
Notice I've removed the Row component as it seem redundant.
I didn't understood why you need two for loops? Do you need 9 inputs or 3 inputs?
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
function Square(props) {
return (<input type='text' id={props.key} value={props.value}></input>);
}
class Box extends React.Component {
constructor(props) {
super(props);
this.state = {
squares: Array(9).fill(null),
xIsNext: true,
};
}
render() {
let board = [];
for (let i = 0; i < 3; i++) {
const key = `${i}row`;
board.push(<Square key={key} value={i} />);
console.log(i)
}
return (board);
}
}
ReactDOM.render(
<Box />,
document.getElementById('root')
);
Upvotes: 0
Reputation: 85545
You should use key in parent element ie. div
in your example:
for( let i=0; i<3;i++){
board.push(<div key={i}><Row /></div>);
}
BTW, you may simply use:
for( let i=0; i<3;i++){
board.push(<Row key={i} />);
}
Best practice is to use some string rather than assigning number value so it will not conflict with other key of element:
for( let i=0; i<3;i++){
board.push(<Row key={'row-'+i} />);
}
Upvotes: 0
Reputation: 3873
Here you need to move key property:
board.push(<div key={i}><Row /></div>);
Because key
should be in the outside element of each element in array
Upvotes: 2