react反模式之index作为key

react反模式之index作为key

原文:Index as a key is an anti-pattern

我已经看到过很多React开发人员在渲染一个列表时使用index作为它的key

{todos.map((todo,index) => 
    <Todo {...todo}
        key={index} />
)}

这样写看起来很优雅并且确实摆脱了react的警告信息,那么这样写有危险的地方吗?


  这样会破坏你的应用让其显示错误的数据

下面我来解释下,key是React来识别DOM元素的唯一属性。如果你往数组里面增加一些元素或者从数组中间移除一些东西会发生些什么呢?如果key属性和以前一样React会认为DOM元素表示的组件和以前是一样的,但是那是错误的。

这里我有简单的例子来演示这个潜在的危险源码

事实证明,React 会用index作为认的key的值因为这个时候React认为用index是最合理的。因此,React会警告你那样做是为达标准的(这样说看起来有点困惑. 如果你自己提供了key属性React会认为你知道自己在做啥. 记住这个例子,它可能会导致错误

Better

列表里面的每一项都应该又一个永久并且唯一的属性,理想情况下应该在创建列表的时候分配下去. 当然我指的是id. 我们可以像下面这样使用它:

{todos.map((todo) => 
    <Todo {...todo}
        key={todo.id} />
)}

另外的实现方式是把编号递增添加到抽象方法中,使用一个全局的index来确保任何两个列表项的id不同。

todoCounter = 1;
function createNewTodo(text) {
    return {
        completed: false,id: todoCounter++,text
    }
}

Much better

一个产品化的解决方案是它应该更加健壮,能够用来创建分散的列表项. 因此我强烈推荐一个npm包shortid,它可以快速生成一系列‘短的 无序的 对url友好的 唯一的’ id,下面是示例代码:

var shortid = require('shortid');

function createNewTodo(text) {
    return {
        completed: false,id: shortid.generate(),text
    }
}

TL;DR: 为每个列表项生成一个唯一的id,然后在渲染列表项时作为key属性传给列表项.

References and related articles

. Dynamic Childrenand Keyed Fragments in React Docs
. Explanation from Paul O’Shannessy
. The importance of component keys in React.js
. React.js and Dynamic Children — Why the Keys are Important

相关文章

react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接...
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc ...