Javascript 返回包含多个子项的列表时,React中唯一的“键”属性

Javascript 返回包含多个子项的列表时,React中唯一的“键”属性,javascript,reactjs,Javascript,Reactjs,我必须在一个react组件中呈现多个列表。我以以下方式创建我的列表: var jobResources = null; if (this.state.jobResources) { jobResources = _.map(this.state.jobResources, function(jobResource, i) { return <ul><li key={i}>{jobResource.resource.name}</li><li

我必须在一个react组件中呈现多个列表。我以以下方式创建我的列表:

var jobResources = null;
if (this.state.jobResources) {
  jobResources = _.map(this.state.jobResources, function(jobResource, i) {
    return <ul><li key={i}>{jobResource.resource.name}</li><li key={Math.floor(Math.random()  * (1000 - 100)) + 100}>{translations.resourceType[jobResource.resource.resourceType.name]}</li></ul>
  })
}
在渲染时,我将列表渲染为:

  <div>
  <h2>Who is Working on the Project?</h2>
  {this.state.jobResources ? jobResources : null}
  </div>
生成的渲染如下所示:

<ul data-reactid=".0.2.0.2.1:0">
  <li data-reactid=".0.2.0.2.1:0.$0">Mark Smith</li>
  <li data-reactid=".0.2.0.2.1:0.$270">Hair &amp; MakeUp</li>
</ul>
<ul data-reactid=".0.2.0.2.1:1">
  <li data-reactid=".0.2.0.2.1:1.$1">John Doe</li>
  <li data-reactid=".0.2.0.2.1:1.$377">Photographer</li>
</ul>
在我看来,钥匙是独一无二的。但是,react给了我以下警告:

警告:数组或迭代器中的每个子级都应具有唯一的键 道具检查JobDetailPage的呈现方法。看见 了解更多信息


有谁能告诉我我犯了什么错误,正确的方法是什么吗?

没关系,算了吧。显然,list元素也应该有一个键。因此,创建列表的正确方法是:

var jobResources = null;
if (this.state.jobResources) {
  jobResources = _.map(this.state.jobResources, function(jobResource) {
    return <ul key={jobResource.id}><li key={jobResource.resource.name}>{jobResource.resource.name}</li><li key={jobResource.resource.resourceType.name}>{translations.resourceType[jobResource.resource.resourceType.name]}</li></ul>
  })
}

lodash/下划线中的此实用程序函数可轻松解决此问题:

key={_.uniqueId()}
我通常这样做

if (this.state.jobResources) {
  jobResources = _.map(this.state.jobResources, function(jobResource, i) {
    return (
      <ul>
        <li key={i.toString()}>{jobResource.resource.name}</li>
        <li key={`key${i}`}>
          {
            translations.resourceType[
              jobResource.resource.resourceType.name
            ]
          }
        </li>
      </ul>
    );
  });
}

仅仅是一个提示,使用一个简单的递增计数器可能会回来咬你,并导致意想不到的结果。而且随机密钥也不是很好。如果jobResource上有某种唯一的ID,最好将其用作UL上的密钥。这样,当您操作列表时,React将在正确的UL上运行,而不是重新绘制整个内容,例如,当您删除作业资源时,将删除底部的UL。至于li元素,键可能只是字符串的名称和类型。@dannyjolie:谢谢你提醒我ul元素,我会改变的。但是,对于li元素,如果两个资源具有相同的名称,那么类型太常见而无法用作键,该怎么办?这将是一个问题,不是吗?它们只需要相对而言是唯一的。也就是说,同一父ul中的两个li元素。不同父元素中的元素很可能具有相同的密钥,因为完整的id是从父元素继承的长字符串,并且在末尾附加了密钥。不客气!我发现key={jobResource.resource.name}可能有点过分了。此外,在resource.name和resource.resourceType.name相同的奇数情况下,它将再次失败。只要你知道总是有两个li元素,你就可以有简单的键,我提到的字符串就足够了,你不必验证任何随机数据。哇,那绝对简单。谢谢生成随机密钥是一项基本实践。即使内容没有更改,它也会强制重新呈现元素。详情如下: