我正在构建一个React组件,它接受JSON数据源并创建一个可排序的表。 每个动态数据行都有一个唯一的键分配给它,但我仍然得到一个错误:

数组中的每个子元素都应该有一个唯一的“key”道具。 检查TableComponent的渲染方法。

我的TableComponent渲染方法返回:

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

TableHeader组件是单行,也有一个唯一的键赋给它。

行中的每一行都是由一个具有唯一键的组件构建的:

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

TableRowItem看起来是这样的:

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

是什么导致唯一键道具错误?


当前回答

您应该为tbody where的每个子键使用唯一的值

该值不能与其同级值相同 不应该在渲染之间改变

例如,键值可以是数据库id或UUID(通用唯一标识符)。

这里的键是手动处理的:

<tbody>
  {rows.map((row) => <ObjectRow key={row.uuid} />)}
</tbody>

你也可以让React使用React. children . toarray来处理键

<tbody>
  {React.Children.toArray(rows.map((row) => <ObjectRow />))}
</tbody>

其他回答

警告:数组或迭代器中的每个子元素都应该有一个唯一的“key”道具。

这是一个警告,因为我们要迭代的数组项需要一个唯一的相似性。

React将迭代组件渲染处理为数组。

更好的解决方法是为你要遍历的数组项提供索引。例如:

class UsersState extends Component
    {
        state = {
            users: [
                {name:"shashank", age:20},
                {name:"vardan", age:30},
                {name:"somya", age:40}
            ]
        }
    render()
        {
            return(
                    <div>
                        {
                            this.state.users.map((user, index)=>{
                                return <UserState key={index} age={user.age}>{user.name}</UserState>
                            })
                        }
                    </div>
                )
        }

index是React内置的道具。

这可能对某些人有帮助,也可能没有,但它可能是一个快速的参考。这也类似于上面给出的所有答案。

我有很多使用下面结构生成列表的位置:

return (
    {myList.map(item => (
       <>
          <div class="some class"> 
             {item.someProperty} 
              ....
          </div>
       </>
     )}
 )
         

经过一些尝试和错误(以及一些挫折)后,向最外层的块添加一个键属性解决了这个问题。另外,注意<>标记现在被<div>标记取代。

return (
  
    {myList.map((item, index) => (
       <div key={index}>
          <div class="some class"> 
             {item.someProperty} 
              ....
          </div>
       </div>
     )}
 )

当然,在上面的例子中,我一直天真地使用迭代索引(index)来填充键值。理想情况下,您应该使用列表项唯一的内容。

这是一个警告,但解决这个问题将使反应渲染更快,

这是因为React需要唯一地标识列表中的每个项。假设在React Virtual DOM中,如果列表中某个元素的状态发生了变化,那么React需要找出哪个元素发生了变化,以及它需要在DOM中的哪个位置发生变化,以便浏览器的DOM与React Virtual DOM保持同步。

作为解决方案,只需为每个li标记引入一个键属性。该键对于每个元素都应该是唯一的值。

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

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

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

这样问题就解决了。

在使用Mongo数据的情况下,您可以使用_id属性

arr.map((cell) =>
  <li key={cell._id}>{cell}
  </li>
);