拥有唯一钥匙时,我会收到唯一钥匙道具警告

时间:2019-03-22 09:30:23

标签: javascript html reactjs reactive-programming

我是React的新手,但我知道唯一密钥的主要概念。但是,我收到警告。

下面我有一个项目组件:

class Item extends Component {
    state = {}

    render() { 
        return ( 
            <React.Fragment>
                {this.props.item.todo}
            </React.Fragment>
        );
    }
}

下面是我的项目组件,其中有唯一的键:

render() { 
    const { items } = this.props;
    return ( 
        items.map(item=>
            <React.Fragment>
                <Item key={item.todo} item={item} />
            </React.Fragment>
        )    
    );
}

所有这些我都得到警告!

5 个答案:

答案 0 :(得分:2)

您需要将key道具放在顶部元素,即React.Fragment而不是Item上。

items.map(item=>
  <React.Fragment key={item.todo}>
    <Item item={item} />
  </React.Fragment>
)    

答案 1 :(得分:2)

您需要将key道具放在顶部元素上,如答案中建议的@Tholle所示。但是在这里,我建议不要使用<React.Fragment>

items.map(item=>
   <Item key={item.todo} item={item} />
)

当您不想使用Fragment<div />等包装器包装元素时,就会使用<p />。由于您拥有<Item />组件,无需使用Fragment

以下是示例,以防您可能使用Fragment

items.map(item=>
   <React.Fragment key={item.todo}>
     <Item item={item} />
     <p>Another Component...</p>
   </React.Fragment>
)

但是,如果您使用Fragment的别名,对不起:<></>不支持key道具。它应该明确设置为完全没有道具。如果需要使用key,则需要用元素将它们包装起来:

items.map(item=>
   <div key={item.todo}>
     <Item item={item} />
     <p>Another Component...</p>
   </div>
)

这将是无效的:

items.map(item=>
   <key={item.todo}>
     <Item item={item} />
     <p>Another Component...</p>
   </>
)

答案 2 :(得分:1)

提供React.Fragment的键

render() { 
  const { items } = this.props;

  return ( 
    items.map(item =>
      <React.Fragment key={item.todo}>
        <Item item={item} />
      </React.Fragment>
    )
  );
}

答案 3 :(得分:1)

正如其他人所说,您需要在顶部元素上设置key,在这种情况下,您需要设置Fragment。但是我会更改键值。我不知道您的item.todo中包含哪种数据,但是仅将密钥设置为item.todo的值可能会出现问题。我会解释。

密钥只能在兄弟姐妹中唯一  列表和键上的react.org文档对此进行了完美的总结,因此我将不作其他解释。它在下面说。

  

数组中使用的键在同级之间应该唯一。但是,它们不必在全球范围内都是唯一的。当我们产生两个不同的数组时,我们可以使用相同的键:

密钥应稳定 这意味着在渲染之间,密钥不应更改,因此请不要使用人们认为会很好使用的Math.random()

为什么上述重要? 在您的数据中,如果两个items.todo的值相同,则会破坏上面的值。您的密钥将不是唯一的。可能由于不必要的重新渲染而导致性能问题。

我建议您使用键值为地图的items.todoindex的键。这样,如果您确实为items.todo添加了相同的值,则添加索引会使密钥唯一。考虑到这一点,我会写你的代码段。

render() { 
  const { items } = this.props;

  return ( 
    items.map((item, index) => (
      <React.Fragment key={item.todo + index}>
        <Item item={item} />
      </React.Fragment>
    ))
  );
}

此处是指向list and keys的react.org文档的链接,也是指向fragments的react.org文档的链接。两者都提供示例和有用的信息。他们是一本好书,我强烈建议。

我还注意到您正在使用React.Fragment,但是随后只用Component声明了您的类。您可以执行我假设您为Component完成的操作,并破坏Fragement的结构。如下所示:

import React, { Component, Fragment } from 'react';

所以您的代码段更加干净,如下所示:

items.map((item, index) => (
  <Fragment key={item.todo + index}>
    <Item item={item} />
  <Fragment>
))

答案 4 :(得分:0)

更好的解决方案是使用shortid npm软件包。它被描述为“惊人的短非顺序url友好的唯一id生成器。”

使用数组索引作为键是一种反模式。进一步了解this article。 ESLINT还可以防止这种情况-> Prevent usage of Array index in keys (react/no-array-index-key)

这是我的用法。

npm install shortid


import shortid from 'shortid'

// using https://www.npmjs.com/package/shortid to prevent duplicate fragment keys
names.map(name => {
    return (
        <Fragment key={`fragment-${id}-${shortid.generate()}`}>
            Hello, {name}!
        </Fragment>
    )
});