我有以下代码(显然这只是一个问题的测试用例,生活更复杂…(。此代码有效,但它给出了警告:
数组或迭代器中的每个子级都应该有一个唯一的"键"道具。
我对React和javascript很陌生,但我确实理解错误,也确实理解为什么需要唯一密钥。正如你所看到的,我确实提供了钥匙,它们确实是独一无二的
var possible_variants = ["A", "B", "C"];
var variant = "";
class App extends React.Component {
render() {
return React.createElement(
"div",
null,
React.createElement(RadioButton, null)
);
}
}
class RadioButton extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
variant = event.target.value;
}
render() {
return React.createElement(
"div",
{
onChange: this.handleChange
},
possible_variants.map(function(my_variant, index) {
return React.createElement(
"label",
null,
React.createElement("input", {
type: "radio",
value: my_variant,
key: my_variant,
name: "variant"
}),
my_variant
);
})
);
}
}
ReactDOM.render(
React.createElement(App, null),
document.getElementById("container")
);
问题似乎是React"希望"密钥在包装标签中,即如果我将映射更改为
possible_variants.map(function(my_variant, index) {
return React.createElement(
"label",
{
key: my_variant // <= here comes the difference
},
React.createElement("input", {
type: "radio",
value: my_variant,
name: "variant"
}),
my_variant
);
});
警告消失了。
所以我的问题是为什么会这样?我从官方文档和网络上的各种教程中了解到,为了获得最佳性能,人们希望关键是最具体的东西,这些东西可能会因重新渲染而改变,这就是这里的输入,而不是一劳永逸的标签。
我是不是错过了什么?
PS:对我来说,这感觉类似于映射警告时的React唯一密钥
首先,我们都知道,需要一个唯一的密钥。
至于代码,第一个代码实际上没有进行键绑定来映射项,而第二个代码则进行了绑定。
请参阅React.createElement文档,每个文档创建一个级别的DOM元素。
在您的第一个代码中,它实际上创建了两次,这意味着您的密钥只绑定在map items
内部,list.map
下的map items
没有任何密钥。
<label>
<input key={...}/>
</label>
第二个让它变得正常,所以它有区别。
<label key={...}>
<input />
</label>
顺便说一句,正如评论所说,你很少有机会使用那些reacttop-level API
,JSX/TSX只是让它更简单。
具体的相关QA。