react反模式——将数组的index作为key

96
我只是个NPC
2017.05.25 17:18* 字数 375

示例

先看一段代码

constructor() {
    super();

    this.state = {
        sort: [{
            name: 'a'
          }, {
            name: 'b'
          }, {
            name: 'c'
        }]
    }
}
...
render() {
    return (
        <ul> 
          {this.state.sort.map((item, index) => {
            return <li key={index}>{item.name} <input type="text"/></li>
          })} 
        </ul>
    ); 
}
...

是不是很眼熟?在很长一段时间,我都是这么设置key来消除react的warning的,然后突然有次发现会出现这样的情况,见下图:

key_index.gif

出现这个情况,是因为react是以key来唯一标识组件的,当发现update前和update后key值没有变化,react就会认为update前后组件是同一个,进而只会对内部的属性进行修改。拿上面的例子来讲,就是react会作出这样的判断:

  • 检测key值,发现都是0,判定组件为同一个;
  • 检测item.name部分,发现有变化,重新渲染这部分;
  • 检测input,发现不依赖props,所以不进行重新渲染;

优化示例

这次我们将key设置为一个特殊字段,保证其唯一性,假设item.name是唯一的。

render() {
    return (
        <ul> 
          {this.state.sort.map((item, index) => {
            return <li key={item.name}>{item.name} <input type="text"/></li>
          })} 
        </ul>
    ); 
}

然后这次再看效果

key_name.gif

这次修改后,react在拿到key后,可以判断出key值和之前不一,再进行对比,发现组件的位置进行了交换,所以做出了符合我们预期的行为。

总结

渲染数组是非常常见的需求,但是选择哪个字段作为key需要慎重考虑,一点要保证其唯一性,尽量避免使用array的索引值作为其key值。

react相关
Web note ad 1