React渲染列表时,会遇到这样的警告:
Warning: Each child in an array or iterator should have a unique "key" prop.
Check the render method of `Game`. See https://fb.me/react-warning-keys for more information.
下面就来谈一下 React 中的 Keys。
文章翻译至React Tutorial:Intro To React
当你渲染一个列表时,React 通常会存储列表中每一项的一些信息。如果你渲染的组件拥有状态,那么这个状态是需要被存储的。并且,不管你的组件是如何实现的,React 都会存储一个可以回退到原生视图的引用。
当你更新列表时,React 需要明确发生了什么变化——列表项增加、删除、排序或者进行了更新。
想象一下列表由下面的状态:
<li>Alexa: 7 tasks left</li>
<li>Ben: 5 tasks left</li>
变成了这样:
<li>Ben: 9 tasks left</li>
<li>Claudia: 8 tasks left</li>
<li>Alexa: 5 tasks left</li>
以人类的思维来看,这个变化应该是 Alexa 和 Ben 交换了位置,并且 Claudia 是新增加的。但是,React 仅仅是计算机程序,它不知道你打算做什么。因此,React 需要你为列表中的每一项指定一个key
属性,这个属性是一个字符串,用来区分组件和它的兄弟姐妹们。在这个事例中,alexa, ben, claudia也许是合适的 keys。如果列表项数据与数据库中存储的格式一致,那么数据 ID 通常是一个好的选择:
<li key={user.id}>{user.name}: {user.taskCount} tasks left</li>
key
是 React 预留的一个特殊属性(与 ref
一样,ref
是一个高级特性)。当元素被创建的时候,React 会把 key 属性直接存储在返回的元素中。虽然它看起来像是 props 的一部分,但是它是不能通过 this.props.key
来引用的。当元素更新时,React 会自动使用 key 来确定更新哪个元素,除此之外,组件没有任何办法去查询它自己的 key。
当列表重新渲染的时候,React 会用新版本列表中的每一项和之前的列表进行 key 的比对。当一个 key 被添加时,一个组件就被创建了;当一个 key 被删除时,一个组件被销毁了。Keys 告诉了 React 每个组件的身份标识,所以,重新渲染的时候,它能够维持组件的状态。如果你改变了一个组件的key,那么它将会被完全销毁并且重新创建一个拥有新状态的组件。
强烈推荐,无论何时,你创建动态列表的时候,都要指定合适的 keys。如果你实在是没有合适的 key,你也许应该考虑重新调整你的数据,以便你能够找到一个合适的 key。
如果你不指定任何 key,React 将会警告你并且回退去使用数组的索引来作为 key。这当然不是一个正确的选择了,因为你通常会为你的列表重新排序等等,除非添加或者删除操作都只发生在列表的底部。显式地通过 key={i}
可以消除警告,但是在很多情况下这样做是有问题的,所以不推荐。
组件的 keys 不需要全局唯一,仅仅让直接兄弟姐妹唯一就可以了。