我正在构建一个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>
    )
  }
});

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


当前回答

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

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

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)来填充键值。理想情况下,您应该使用列表项唯一的内容。

其他回答

我遇到这个错误消息,因为<></>被返回数组中的一些项目,而不是null需要返回。

我认为在处理表(或类似的例子)时,为了重用性,应该将创建的唯一键从父组件传递给子组件。

因为如果你正在创建一个表,这意味着你正在从父表传递数据。如果你赋值key={row.name},可能当前数据有name属性,但如果你想在其他地方使用这个表组件,你假设在你传递的每一行数据中,你都有name属性。

由于工程师将在父组件中准备数据,因此工程师应该基于这些数据创建一个键函数。

const keyFunc = (student) => {
    return student.id;
  }; 

在这种情况下,工程师知道它正在发送什么数据,它知道每一行都有唯一的id属性。也许在不同的数据集中,数据集是股票价格它没有id属性,只有符号

 const keyFunc = (stock) => {
        return stock.symbol;
      }; 

这个keyFunc应该作为道具传递给子组件,以保证可重用性和唯一性。

列表中的每个子元素都应该有一个唯一的“key”道具。

通过在呈现元素中的key属性中声明index值来解决。

App.js组件

import Map1 from './Map1';

const arr = [1,2,3,4,5];

const App = () => {
  return (
    <>
     
     <Map1 numb={arr} />     

    </>
  )
}

export default App

Map.js组件

const Map1 = (props) => {

    let itemTwo = props.numb;
    let itemlist = itemTwo.map((item,index) => <li key={index}>{item}</li>)

    return (
        <>        
        <ul>
            <li style={liStyle}>{itemlist}</li>
        </ul>
        </>
    )
}

export default Map1

一个直观的解释。

(数组的)key=index的错误方式

正如你所看到的,标签3、标签2和标签1都被重新渲染了(在元素面板中闪烁)。

正确的方法是key=uniqueId

只有顶部的新元素会闪烁(重新渲染)。

您应该为每个子元素以及子元素中的每个元素添加一个键。

这样React就可以处理最小的DOM更改。

在代码中,每个<TableRowItem key={项。id} data={item} columns={columnNames}/>试图在其中呈现一些没有键的子元素。

请看这个例子。

尝试从div的<b></b>元素中删除key={i}(并检查控制台)。

在本例中,如果我们没有给<b>元素一个键,并且我们只想更新对象。在city中,React需要重新渲染整个行,而不仅仅是元素。

代码如下:

const data = [
  { name: "Nuri", age: 28, city: "HO" },
  { name: "Talib", age: 82, city: "HN" },
  { name: "Jenny", age: 41, city: "IT" },
];

const ExampleComponent = React.createClass({
  render: function () {
    const infoData = this.props.info;
    return (
      <div>
        {infoData.map((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(<ExampleComponent info={data} />, document.body);

下面由@Chris发布的答案比这个答案更详细。

React文档中关于按键在协调中的重要性:按键