開發(fā)者要了解index作為key是反模式
我曾多次看到開發(fā)者在渲染列表的時候把列表項的index作為它的key。
- {todos.map((todo, index) =>
- <Todo {...todo}
- key={index} />
- )}
這看起來很優(yōu)雅,而且能夠解決警告(這才是“真”問題,對吧?)的問題,這樣做有什么危險呢?
It may break your application and display wrong data!
讓我來解釋,key是React唯一用來確定DOM元素的東西,如果你想列表增加一項或移除中間的某項,會發(fā)生什么事?如果key和之前一個一樣React就會假定這個DOM元素和之前對應(yīng)的組件是一個,但是它們可能并不是同一個了。
為了證明潛在的危險我創(chuàng)建了一個簡單示例
這表明,如果不指定key的時候React會使用index,因為這是那個時候最好的猜測,而且它會警告你說這不是最優(yōu)解(它通過令人困惑的語句表述這個意思)。如果你主動提供了它,React就認(rèn)為你知道你在干什么。記住這個示例,它能產(chǎn)生不可預(yù)測的結(jié)果。
比較好
像這樣的應(yīng)該都有一個永久的唯一的屬性,當(dāng)列表項創(chuàng)建的時候它是最合適被設(shè)置為key的,顯然我是在說id,我們可以用下面的方式使用它:
- {todos.map((todo) =>
- <Todo {...todo}
- key={todo.id} />
- )}
另外的實現(xiàn)方式是把編號遞增移動到抽象方法中,使用一個全局的index來確保任何兩個列表項的id不同。
- todoCounter = 1;
- function createNewTodo(text) {
- return {
- completed: false,
- id: todoCounter++,
- text
- }
- }
更好
一個產(chǎn)品級別的方案應(yīng)該是一個更健壯的方法,能夠處理分散創(chuàng)建列表項。因此,我推薦使用shortid。它能夠快速生成“短 無序 url友好 唯一”的id,代碼像下面這樣:
- var shortid = require('shortid');
- function createNewTodo(text) {
- return {
- completed: false,
- id: shortid.generate(),
- text
- }
- }
TL;DR:為每個列表項生成一個唯一的id,并在渲染列表的時候使用它作為key。