我是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>
)
);
}
所有这些我都得到警告!
答案 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.todo
和index
的键。这样,如果您确实为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>
)
});