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=idkey=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