Understanding unique keys for array children in React.js

Brett DeWoody picture Brett DeWoody · Feb 4, 2015 · Viewed 702.7k times · Source

I'm building a React component that accepts a JSON data source and creates a sortable table.
Each of the dynamic data rows has a unique key assigned to it but I'm still getting an error of:

Each child in an array should have a unique "key" prop.
Check the render method of TableComponent.

My TableComponent render method returns:

<table>
  <thead key="thead">
    <TableHeader columns={columnNames}/>
  </thead>
  <tbody key="tbody">
    { rows }
  </tbody>
</table>

The TableHeader component is a single row and also has a unique key assigned to it.

Each row in rows is built from a component with a unique key:

<TableRowItem key={item.id} data={item} columns={columnNames}/>

And the TableRowItem looks like this:

var TableRowItem = React.createClass({
  render: function() {

    var td = function() {
        return this.props.columns.map(function(c) {
          return <td key={this.props.data[c]}>{this.props.data[c]}</td>;
        }, this);
      }.bind(this);

    return (
      <tr>{ td(this.props.item) }</tr>
    )
  }
});

What is causing the unique key prop error?

Answer

jmingov picture jmingov · Feb 4, 2015

You should add a key to each child as well as each element inside children.

This way React can handle the minimal DOM change.

In your code, each <TableRowItem key={item.id} data={item} columns={columnNames}/> is trying to render some children inside them without a key.

Check this example.

Try removing the key={i} from the <b></b> element inside the div's (and check the console).

In the sample, if we don't give a key to the <b> element and we want to update only the object.city, React needs to re-render the whole row vs just the element.

Here is the code:

var data = [{name:'Jhon', age:28, city:'HO'},
            {name:'Onhj', age:82, city:'HN'},
            {name:'Nohj', age:41, city:'IT'}
           ];

var Hello = React.createClass({

    render: function() {

      var _data = this.props.info;
      console.log(_data);
      return(
        <div>
            {_data.map(function(object, i){
               return <div className={"row"} key={i}> 
                          {[ object.name ,
                             // remove the key
                             <b className="fosfo" key={i}> {object.city} </b> , 
                             object.age
                          ]}
                      </div>; 
             })}
        </div>
       );
    }
});

React.render(<Hello info={data} />, document.body);

The answer posted by @Chris at the bottom goes into much more detail than this answer. Please take a look at https://stackoverflow.com/a/43892905/2325522

React documentation on the importance of keys in reconciliation: Keys