我正在构建一个React组件,它接受一个JSON数据源并创建一个可排序表。
每个动态数据行都有一个唯一的键分配给它,但我仍然得到一个错误:
数组中的每个子项都应该有一个唯一的“键”道具。
检查TableComponent的render方法。
我的TableComponent
呈现方法返回:
<table>
<thead key="thead">
<TableHeader columns={columnNames}/>
</thead>
<tbody key="tbody">
{ rows }
</tbody>
</table>
tableheader
组件是单行,并且还为其分配了唯一的键。
rows
中的每个row
都是由具有唯一键的组件生成的:
<TableRowItem key={item.id} data={item} columns={columnNames}/>
而TableRoWitem
如下所示:
var TableRowItem = React.createClass({
render: function() {
var td = function() {
return this.props.columns.map(function(c) {
return <td key={this.props.data[c]}>{this.props.data[c]}</td>;
}, this);
}.bind(this);
return (
<tr>{ td(this.props.item) }</tr>
)
}
});
是什么原因导致了唯一键道具错误?
您应该为每个子元素以及子元素中的每个元素添加一个键。
这样React就可以处理最小的DOM更改。
在您的代码中,每个
都试图在没有键的情况下呈现它们内部的一些子项。
请查看此示例。
尝试从div的元素中删除
key={i}
(并检查控制台)。
在示例中,如果我们不给元素一个键,并且只想更新
object.city
,React需要重新呈现整行,而不是只呈现元素。
代码如下:
var data = [{name:'Jhon', age:28, city:'HO'},
{name:'Onhj', age:82, city:'HN'},
{name:'Nohj', age:41, city:'IT'}
];
var Hello = React.createClass({
render: function() {
var _data = this.props.info;
console.log(_data);
return(
<div>
{_data.map(function(object, i){
return <div className={"row"} key={i}>
{[ object.name ,
// remove the key
<b className="fosfo" key={i}> {object.city} </b> ,
object.age
]}
</div>;
})}
</div>
);
}
});
React.render(<Hello info={data} />, document.body);
@chris在下方贴出的答案比这个答案要详细得多。请查看https://stackoverflow.com/a/43892905/2325522
对核对中关键字的重要性做出反应:关键字
迭代数组时要小心!!
一个常见的误解是,使用数组中元素的索引是抑制您可能熟悉的错误的一种可接受的方法:
Each child in an array should have a unique "key" prop.
然而,很多情况下并非如此!这是反模式,在某些情况下会导致不想要的行为。
React使用key
道具来理解组件到DOM元素的关系,然后将其用于协调过程。因此,关键字始终保持唯一是非常重要的,否则,React很有可能会混淆元素并变异出不正确的元素。同样重要的是,这些键在所有重新呈现过程中保持静态,以保持最佳性能。
话虽如此,但只要已知数组是完全静态的,就不一定需要应用上述内容。不过,只要有可能,就鼓励采用最佳做法。
一位React开发者在本期GitHub中表示:
简而言之,键
应该是:
根据上面的解释,仔细研究以下示例,并尽可能地实现推荐的方法。
<tbody>
{rows.map((row, i) => {
return <ObjectRow key={i} />;
})}
</tbody>
这可能是在React中迭代数组时最常见的错误。这种方法在技术上并不“错误”,只是...“危险”如果你不知道自己在做什么。如果您正在迭代一个静态数组,那么这是一个完全有效的方法(例如,导航菜单中的链接数组)。但是,如果您正在添加、删除、重新排序或筛选项目,那么您就需要小心了。看看官方文档中的这篇详解吧。
null
class MyApp extends React.Component {
constructor() {
super();
this.state = {
arr: ["Item 1"]
}
}
click = () => {
this.setState({
arr: ['Item ' + (this.state.arr.length+1)].concat(this.state.arr),
});
}
render() {
return(
<div>
<button onClick={this.click}>Add</button>
<ul>
{this.state.arr.map(
(item, i) => <Item key={i} text={"Item " + i}>{item + " "}</Item>
)}
</ul>
</div>
);
}
}
const Item = (props) => {
return (
<li>
<label>{props.children}</label>
<input value={props.text} />
</li>
);
}
ReactDOM.render(<MyApp />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>