文章首發於github博客react
以前在寫react的時候,當咱們作map循環的時候,當咱們沒有一個惟一id來標識每一項item的時候,咱們可能會選擇使用indexgit
data.map((item, index) => {
return <li key={index}>{item}</li>
})
複製代碼
可是其實當你使用index來做爲惟一key的時候,實際上是由一個大坑的,什麼坑呢?必須坑了你才知道,來看下面的這種狀況:github
class App extends React.Component{
constructor(props) {
super(props)
this.state = {
list: [{id: 1,val: 'aa'}, {id: 2, val: 'bb'}, {id: 3, val: 'cc'}]
}
}
click() {
this.state.list.reverse()
this.setState({})
}
splice() {
this.state.list.splice(1,1)
this.setState({})
}
render() {
return (
<ul>
<div onClick={this.splice.bind(this)}>delete</div>
<div onClick={this.click.bind(this)}>reverse</div>
{
this.state.list.map(function(item, index) {
return (
<Li key={index} val={item.val}></Li>
)
}.bind(this))
}
</ul>
)
}
}
class Li extends React.Component{
constructor(props) {
super(props)
}
componentDidMount() {
console.log('===mount===')
}
componentWillUpdate(nextProps, nextState) {
console.log('===update====')
}
render() {
return (
<li>
{this.props.val}
<input type="text"></input>
</li>
)
}
}
複製代碼
頁面渲染好了以後,3個input輸入框依次輸入1,2,3: 當咱們用index做爲key的時候,點擊reverse會發現,input輸入框仍是1,2,3順序顯示,可是這並不符合咱們的預期,控制檯中此時打印的也是update; 當咱們用對象中的id做爲key的時候,點擊reverse,此時神奇的事情發生了,input輸入框變成了3,2,1,符合咱們的預期,控制檯此時打印的也是update;算法
爲何會這樣呢?bash
當咱們傳入index做爲key時,此時的key爲0,1,2, 當咱們點擊reverse從新排序後,index傳進去的key仍是0,1,2,此時react比較key=0時,發現只須要更新子節點的值就能夠,因而只把item替換成了cc,而input則相反, 當咱們傳入id做爲index的時候,,點擊reverse後,此時的key變成了3,2,1,根據react的diff算法,react仍是能分辨出只須要移動子節點便可完成更新,所以input也隨之變化。ui
那說了這麼多,其實對於index做爲key咱們是不推薦的,除非你可以保證他們不會發生變化。this
參考文獻 index as a key is an anti-pattern, 有問題能夠在博客下方留言,感謝starspa