了解React.js中的数组子项的唯一键
我正在构build一个接受JSON数据源的React组件,并创build一个可sorting的表。
每个dynamic数据行都有一个唯一的键分配给它,但我仍然得到一个错误:
arrays中的每个孩子应该有一个独特的“钥匙”道具。
检查TableComponent的渲染方法。
我的TableComponent
渲染方法返回:
<table> <thead key="thead"> <TableHeader columns={columnNames}/> </thead> <tbody key="tbody"> { rows } </tbody> </table>
TableHeader
组件是一个单独的行,也有一个唯一的键分配给它。
row
中的每一rows
都是由一个具有唯一键的组件构build的:
<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更改。
在你的代码中,每个<TableRowItem key={item.id} data={item} columns={columnNames}/>
都试图在没有密钥的情况下呈现其中的一些子<TableRowItem key={item.id} data={item} columns={columnNames}/>
。
检查这个例子 。
尝试从div内的<b></b>
元素中移除key={i}
(并检查控制台)。
在示例中,如果我们没有给出<b>
元素的关键字,并且我们只想更新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 , <b className="fosfo" key={i}> {object.city} </b> , // remove the key object.age ]} </div>; })} </div> ); } }); React.render(<Hello info={data} />, document.body);
反应关键在和解中的重要性的文件: 钥匙
迭代数组时要小心!
使用数组中元素的索引是一个可以接受的方法来抑制每个人都熟悉的错误是一个常见的误解:
Each child in an array should have a unique "key" prop.
但是,这不是! 这是反模式 ,可以在某些情况下导致不需要的行为 。
了解key
道具
React使用key
prop来理解component-to-DOM元素关系,然后将其用于对帐过程 。 因此,关键是永远保持唯一性是非常重要的,否则React会混淆元素并改变错误的元素。 为了保持最佳性能,在所有重新渲染过程中,这些键保持静态也是很重要的。
这就是说,人们并不总是需要应用上述,只要知道arrays是完全静态的。 但是,尽可能鼓励应用最佳做法。
React开发人员在这个GitHub的问题上说 :
- 关键不在于性能,而在于身份(反过来导致更好的性能)。 随机分配和变化的值不是身份
- 我们不能在不知道数据如何build模的情况下实际提供密钥。 我build议也许使用某种哈希函数,如果你没有ID
- 当我们使用数组时,我们已经有了内部键,但是它们是数组中的索引。 当你插入一个新元素时,这些键是错误的。
总之,一个key
应该是:
- 唯一 – 密钥不能与兄弟组件的密钥相同。
- 静态 – 一个键不应该在渲染之间改变。
使用key
道具
根据上面的解释,仔细研究以下样本,尽可能实施推荐的方法。
不好(可能)
<tbody> {rows.map((row, i) => { return <ObjectRow key={i} />; })} </tbody>
这可以说是在React中迭代数组时最常见的错误。 这种方法将正常工作,除非元素被添加到rows
数组或从rows
数组中移除。 如果你正在迭代静态的东西,那么这是完全有效的(例如,导航菜单中的一系列链接)。 在官方文档中查看这个详细的解释 。
下面是一个代码片段,演示了使用数组的项索引作为key
的风险:
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="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>