Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

该不该用index作为react列表中的key #2

Open
wangweida opened this issue May 16, 2017 · 0 comments
Open

该不该用index作为react列表中的key #2

wangweida opened this issue May 16, 2017 · 0 comments

Comments

@wangweida
Copy link
Owner

wangweida commented May 16, 2017

问题

今天再使用airbnb的eslint写react的时候有一个很意外的报错,Do not use Array index in keys,不允许用index来作为列表的key,情况类似以下代码

data.map((item, index) => {
	return(
		<li key={index}>{item}</li>
	);
})

因为不管是react还是vue通常这种列表的渲染,如果本身没有id的话我都会把key传成index,而且react官方文档中也有一个例子,同样如此,好像并没有遇到什么问题,所以带着点好奇心查了一下这条规则。

原因

这条规则的解释(需要科学上网) 规则解释 里给了一个这样的例子,Avoid using an array index as key prop,并且解释了原因——使用index作为key的列表,向列表中添加或删除某些项时可能导致错误的显示。因为key是连接真实dom的标识,当更改后的key与更改前的key相同时,react会认为前后的组件是相同的,但其实这两项并不一样。

我感觉这里解释的略微有点模糊,所以想再写的详细一点。其实如果能懂得上面的例子中基于 key={index} 的列表,当点击add-item-btn时,dom所作的操作并不是在列表的最前面插入一项(insert),而是再最后添加一项(append)的话,建议你可以跳过下面的内容。

我们知道在react中渲染一个列表的时候,会要求传入key属性,其实这主要是出于react对性能的考虑。当组件被传入的属性或状态发生改变时,render会重新触发,所以,在一个不确定长度的数组中,react需要基于key去判断整个列表结构,从而操作列表中的dom,大体上有三种情况。

1. 当有新key时,则创建新节点
2. 当有key消失时,则销毁key所对应的节点
3. 当key相同,则更新对应节点

知道了key的作用,下一步就是理解上面那个例子的解释,在这里我们举几个更简单的例子

// 将 [{name: a, id: 0}, {name: b, id: 1}] 
// 转变成 [{name: a, id: 0}, {name: c, id: 1}]  

很明显的,这里无论是用index作为key或是id作为key,key值前后都是相同的,所以只要对应更新第二个节点中的内容就可以了

// 将 [{name: a, id: 0}, {name: b, id: 1}] 
// 转变成 [{name: a, id: 0}, {name: c, id: 1}, {name: d, id: 2}]  

这种情况中,无论是用index作为key或是id作为key,都是对应的更新第二个节点,然后创建第三个节点append到列表中

// 将 [{name: a, id: 0}, {name: b, id: 1}] 
// 转变成 [{name: c, id: 2}, {name: a, id: 0}, {name: b, id: 1}]  

这种情况是最接近最开始的例子的,我们希望的是创建一个新的节点然后插入到列表的最前面。
当用id作为key时,很显然,key为0的节点与key为1的节点都不用进行任何变化,只有key为2的节点需要被创建然后insert到列表中。
当用index作为key时,key为0与1的节点都需要被更新,此外还有创建key为2的节点,然后append到列表中。无论是性能与实际的dom操作其实都不符合我们的预期。


结尾

理解了上面的例子就可以知道为什么airbnb中用index来作key会被报错。 规则解释 这条规则的解释中也提供给了我们几种方法去避免这种情况的发生,有兴趣的话也可以一起看完。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant