当前位置: 首页 > 知识库问答 >
问题:

了解React.js中数组子项的唯一键

席俊驰
2023-03-14

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

数组中的每个子项都应该有一个唯一的“键”道具。
检查TableComponent的render方法。

我的TableComponent呈现方法返回:

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

tableheader组件是单行,并且还为其分配了唯一的键。

rows中的每个row都是由具有唯一键的组件生成的:

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

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

共有2个答案

冯新知
2023-03-14

迭代数组时要小心!!

一个常见的误解是,使用数组中元素的索引是抑制您可能熟悉的错误的一种可接受的方法:

Each child in an array should have a unique "key" prop.

然而,很多情况下并非如此!这是反模式,在某些情况下会导致不想要的行为。

React使用key道具来理解组件到DOM元素的关系,然后将其用于协调过程。因此,关键字始终保持唯一是非常重要的,否则,React很有可能会混淆元素并变异出不正确的元素。同样重要的是,这些键在所有重新呈现过程中保持静态,以保持最佳性能。

话虽如此,但只要已知数组是完全静态的,就不一定需要应用上述内容。不过,只要有可能,就鼓励采用最佳做法。

一位React开发者在本期GitHub中表示:

  • 关键不是真正的性能,它更多的是身份(这反过来又会导致更好的性能)。随机分配和更改的值不是标识
  • 如果不知道您的数据是如何建模的,我们就无法实际地[自动]提供密钥。如果您没有ID
  • ,我建议使用某种散列函数
  • 我们在使用数组时已经有了内部键,但它们是数组中的索引。插入新元素时,这些键是错误的。

简而言之,应该是:

  • 唯一-密钥不能与同级组件的密钥相同。
  • 静态-键不应在呈现之间更改。

根据上面的解释,仔细研究以下示例,并尽可能地实现推荐的方法。

<tbody>
    {rows.map((row, i) => {
        return <ObjectRow key={i} />;
    })}
</tbody>

这可能是在React中迭代数组时最常见的错误。这种方法在技术上并不“错误”,只是...“危险”如果你不知道自己在做什么。如果您正在迭代一个静态数组,那么这是一个完全有效的方法(例如,导航菜单中的链接数组)。但是,如果您正在添加、删除、重新排序或筛选项目,那么您就需要小心了。看看官方文档中的这篇详解吧。

null

class MyApp extends React.Component {
  constructor() {
    super();
    this.state = {
      arr: ["Item 1"]
    }
  }
  
  click = () => {
    this.setState({
      arr: ['Item ' + (this.state.arr.length+1)].concat(this.state.arr),
    });
  }
  
  render() {
    return(
      <div>
        <button onClick={this.click}>Add</button>
        <ul>
          {this.state.arr.map(
            (item, i) => <Item key={i} text={"Item " + i}>{item + " "}</Item>
          )}
        </ul>
      </div>
    );
  }
}

const Item = (props) => {
  return (
    <li>
      <label>{props.children}</label>
      <input value={props.text} />
    </li>
  );
}

ReactDOM.render(<MyApp />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
罗安和
2023-03-14

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

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

在您的代码中,每个 都试图在没有键的情况下呈现它们内部的一些子项。

请查看此示例。

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

在示例中,如果我们不给元素一个键,并且只想更新object.city,React需要重新呈现整行,而不是只呈现元素。

代码如下:

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

@chris在下方贴出的答案比这个答案要详细得多。请查看https://stackoverflow.com/a/43892905/2325522

对核对中关键字的重要性做出反应:关键字

 类似资料:
  • 我正在构建一个React组件,它接受一个JSON数据源并创建一个可排序表。 每个动态数据行都有一个唯一的键分配给它,但我仍然得到一个错误: 数组中的每个子项都应该有一个唯一的“键”道具。 检查TableComponent的render方法。 我的呈现方法返回: 组件是单行,并且还为其分配了唯一的键。 中的每个都是由具有唯一键的组件生成的: 而如下所示: 是什么原因导致了唯一键道具错误?

  • 我使用React来呈现数据列表,但是数据中的每一项都没有被分配id或uuid或类似于标识属性的东西。我可以使用项目索引作为关键吗?喜欢: 我所关心的是,如果页面上的其他列表也使用order索引作为子组件键,这有关系吗?钥匙应该是唯一的标识吗?

  • 编辑:下面由BlueSignal提供的链接是最适用的答案。它不仅解释了这种行为发生的原因,而且为所述问题提供了解决方案。 我有一个数组,我想确定是否所有元素都等于一个值。下面的代码似乎应该起作用,但没有。有人能解释一下吗? 任何信息都将是最受欢迎的!

  • 问题内容: 我很新,我现在真的非常困惑。 假设我有一个坐标列表,并且说我在此坐标列表中有一些双打。我一辈子都无法弄清楚如何制作一份独特的清单。通常,在Python中,我可以“欺骗”集合和其他内置函数。在Go中没有那么多。 问题答案: 您的代码中存在多个错误。最严重的是,由于您要将切片的每个特定元素与的 所有 元素进行比较,因此如果包含至少一个不同的元素,最终将附加它。而且,如果由于内部循环不会“中

  • 问题内容: 在处理从YQL返回的JSON时,我发现自己正在寻找一种从数组中提取所有唯一值的方法。 代码看起来有点“忙”,我想知道是否有更优雅的方法从数组中提取唯一值。 问题答案: 您可以使用indexOf来检查元素是否在数组中。 或者如果您具有唯一的ID或名称,则使用对象而不是数组:var output = {}

  • 我的应用程序中有以下Dagger2架构: 其中:AppComponent: UserComponent: ActivityComponent: ChatComponent: 首先,如何将不同的注入到类中?要么是应用程序,要么是活动?? 其次,我在编译代码时遇到了一个奇怪的问题,错误是: 错误:(23,10)错误:br.com.animaeducacao.ulife.domain.interacto