共计 2369 个字符,预计需要花费 6 分钟才能阅读完成。
1、key 是什么
Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity.
key
是用来帮助 react
识别哪些内容被更改、添加或者删除。key
需要写在用数组渲染出来的元素内部,并且需要赋予其一个稳定的值。稳定在这里很重要,因为如果 key
值发生了变更,react
则会触发 UI
的重渲染。这是一个非常有用的特性。key
就是元素的唯一标识,相当于身份证一样。
2、key 的作用
给 key
赋值一般采用两种方式,一种是赋值 index
(索引),一种是赋值id
(这里用id
表示稳定标识),我们举个例子来看看两者之间的区别。
key=index 例子:
ToDo 组件:
import React from 'react'
import {number, object} from 'prop-types'
const ToDo = ({id, createAt}) => (
<tr>
<td>
<label>{id}</label>
</td>
<td>
<input />
</td>
<td>
<label>{createAt.toTimeString()}</label>
</td>
</tr>
)
ToDo.propTypes = {
id: number.isRequired,
createAt: object.isRequired
}
export default ToDo
ToDoList 组件:
import React, {Component} from 'react'
import ToDo from '../ToDo'
export default class ToDoList extends Component {
state = {
todoCounter: 1,
list: [{ id: 1, createAt: new Date() }
]
}
addStart = () => {
this.setState(prevState => ({list: [{ id: prevState.todoCounter + 1, createAt: new Date() }, ...prevState.list],
todoCounter: prevState.todoCounter + 1
}))
}
addEnd = () => {
this.setState(prevState => ({list: [...prevState.list, { id: prevState.todoCounter + 1, createAt: new Date() }],
todoCounter: prevState.todoCounter + 1
}))
}
sortEarly = () => {
this.setState(prevState => ({list: prevState.list.sort((a, b) => {return a.createAt - b.createAt})
}))
}
sortLate = () => {
this.setState(prevState => ({list: prevState.list.sort((a, b) => {return b.createAt - a.createAt})
}))
}
render () {
return (
<div>
<code>key=index</code>
<br />
<button onClick={this.addStart}>add new to start</button>
<button onClick={this.addEnd}>add new to end</button>
<button onClick={this.sortEarly}>sorted by earliest</button>
<button onClick={this.sortLate}>sorted by latest</button>
<table>
<tr>
<th>ID</th>
<th>Input</th>
<th>create at</th>
</tr>
{this.state.list.map((item, index) => (<ToDo key={index} {...item}></ToDo>
))
}
</table>
</div>
)
}
}
结果:
key=id 例子:
我们将 <ToDo key={index} {...item}></ToDo>
改成<ToDo key={item.id} {...item}></ToDo>
, 结果为:
我们可以看到 key=id
和key=index
时应用程序表现结果是不相同的,不相同之处表现在 input
输入值有没有随着排序而改变。我们来解释一下产生这种结果的原因 ( 元素类型相同时,key 值相同的元素标识同一个元素)。
当 key=index 时
当 key=id 时
一个是元素位置没变,重新渲染数据;一个是位置变了,数据没变,只需要移动位置,所以才导致上面现象。当我们的列表数据非常庞大时,重新渲染的代价是很高的,正确的使用 key
值可以帮助我们减少渲染量,做到及时响应,这也是 react
的一大优点。
参考:
https://medium.com/@adhithiravi/why-do-i-need-keys-in-react-lists-dbb522188bbb
https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318
https://zhuanlan.zhihu.com/p/45091185
https://juejin.im/post/5a7c04746fb9a063461fe700
https://juejin.im/post/59abb01c518825243f1b6dad