Javascript 如何找到警告的原因:列表中的每个孩子都应该有一个唯一的;“关键”;道具

Javascript 如何找到警告的原因:列表中的每个孩子都应该有一个唯一的;“关键”;道具,javascript,reactjs,Javascript,Reactjs,我经常遇到错误 Warning: Each child in a list should have a unique "key" prop. Check the render method of `MyComponent`. 在反应中。错误消息总是告诉您有问题的组件,而不是有问题的特定HTML标记/虚拟DOM元素。在大型代码库中工作,有时使用大型组件,这使得查找错误源非常困难 是什么原因导致此错误?我正在寻找一份明确的清单。 数组中完全缺少“键”道具的标记(非常确定) 数组中具有相同“键”

我经常遇到错误

Warning: Each child in a list should have a unique "key" prop.  Check the render method of `MyComponent`.
在反应中。错误消息总是告诉您有问题的组件,而不是有问题的特定HTML标记/虚拟DOM元素。在大型代码库中工作,有时使用大型组件,这使得查找错误源非常困难

是什么原因导致此错误?我正在寻找一份明确的清单。

  • 数组中完全缺少“键”道具的标记(非常确定)
  • 数组中具有相同“键”属性值的两个标记?(我以为这是另一个错误消息)
并排写入的两个元素(如
)是否算作“列表中的子元素”?它们也会导致错误吗

寻找攻击性标签的有效策略是什么?

  • key={Math.random()}
    逐个添加到组件中的每个无键标记,直到错误消失,然后查看最后添加的是哪一个。(可能很耗时,有时不起作用)
  • 按时间顺序撤消更改,直到错误消失。(可能很耗时)
  • 这里有更好的吗

我正在寻找一个彻底而规范的答案。

在jsx中查找
map
调用,可以找到令人不快的部分。映射中的每个顶级元素都应该具有
属性,即

{items.map(item => (
  <div key={item.id}>
    <div>{item.name}</div>
    <div>{item.description}</div>
  </div>
))}
这里有问题的文件名为
Log.js
,第241行。我不知道跟踪是否总是存在且正确,但它可能会有所帮助


至于我,我经常在浏览器中检查结果,控制台通常是打开的,所以当我看到那个警告时,我通常知道我最近对数组做了什么,以及我忘记了键的位置。

这里是一个基于我迄今所学的部分答案

什么/不导致此错误?以下是一份清单:
  • 数组中缺少“键”属性的标记会导致错误。比如说,

    <Fragment>
        {[
            <div>one</div>
        ]}
    </Fragment>
    
    <Fragment>
        <div>one</div>
    </Fragment>```
    
    <Fragment>
        {[
            <div key={undefined}>one</div>
        ]}
    </Fragment>```
    
    <Fragment>
        {[
            <div key={'chicken'}>one</div>,
            <div key={'chicken'}>one</div>
        ]}
    </Fragment>```
    
  • 给出错误,即使键入了密钥道具。注意这一点很重要,因为这意味着您可以将一个变量分配给键属性,但仍然会遇到此错误。例如,可能有坏数据进入应用程序,因此
    key={myobj.id}
    触发错误,因为
    myobj.id
    未定义

  • 数组中带有“键”属性且定义值重复的标记不会导致错误。比如说,

    <Fragment>
        {[
            <div>one</div>
        ]}
    </Fragment>
    
    <Fragment>
        <div>one</div>
    </Fragment>```
    
    <Fragment>
        {[
            <div key={undefined}>one</div>
        ]}
    </Fragment>```
    
    <Fragment>
        {[
            <div key={'chicken'}>one</div>,
            <div key={'chicken'}>one</div>
        ]}
    </Fragment>```
    
    
    {[
    一,,
    一
    ]}
    ```
    
  • 即使键不是唯一的,也不会给出错误

    是什么导致了这个错误?总之:
    当存在一个
    数组
    时,该数组包含一个标记项,该标记项未分配
    属性,或者有一个键属性的赋值为
    未定义

    当您必须在React中渲染数组时,您将使用
    映射
    函数

    如果渲染组件中有一个映射函数,则它返回的根元素将采用一个键属性,该属性必须是唯一的。这是为了优化列表的呈现

    const names = ['John', 'Sam', 'Charlie'];
    {
      names.map( (name, index) =>
        <div key={index}>
          <Foo />
          <Bar />
        </div>
      )
    }
    
    const name=['John','Sam','Charlie'];
    {
    names.map((名称,索引)=>
    )
    }
    
    要解决
    MyComponent
    中的问题,应首先确定元素映射的位置,然后添加
    属性。如果数组中没有唯一标识符,那么即使是索引(如上面代码段中所述)也是一个很好的候选。如果它是用户对象的数组;电子邮件ID或用户ID看起来很有希望。

    并给出了很好的答案,回答了您的大部分问题

    这是我的2美分:

    是什么导致了这个错误?我在找一份确定的名单。 数组中完全缺少“键”道具的标记(非常确定)

    是的!您可能有重复的密钥,或者密钥完全丢失

    数组中具有相同“键”属性值的两个标记?(我以为这是另一个错误消息)

    具有相同键的两个元素将抛出相同的警告。该警告在生产模式下不显示,仅在开发模式下显示。 拥有重复的键也会导致奇怪的行为:具有相同键的元素不会正确更新或保留旧道具。如果列表中的元素没有更改,则这一点不明显-例如:渲染列表中的元素从未更改

    并排写的两个元素(例如)算作“列表中的子元素”吗?它们也会导致错误吗

    不会。这不会导致错误。 “键有助于识别哪些项目已更改、已添加或已删除。”- 这些div是静态代码-它们从不更改,因此不需要密钥


    寻找攻击性标签的有效策略是什么? 将key={Math.random()}逐个添加到组件中的每个无键标记,直到错误消失,然后查看最后添加的是哪一个。(可能很耗时,有时不起作用)

    对列表项使用随机键不是一个好主意。 在每次渲染时生成一个随机键意味着所有列出的组件都将更新(重新渲染),即使道具没有更改。 我会将此作为最后手段,对于大型列表(或应用程序),这可能会有性能问题

    当我没有
    id
    用作键时,而不是
    random
    ,我喜欢使用
    index
    并组成一个键-ex:
    list.map((elem,index)=>{elem.name})
    使用索引作为键被认为是一个问题,但它确实可以帮助您解决这个问题

    为键合成名称后,您可以很容易地在代码中找到引发警告的组件-例如:find add
    some element-
    ,因为警告显示重复键的名称

    按时间顺序撤消更改,直到错误消失