简体   繁体   中英

Rendering an array of objects in react

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')
  );

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

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} />);
}

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')
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM