乐趣区

react中key的使用

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

退出移动版