React中使用map遍历元素时key为index遇到的坑

原创 潇洒先生 随笔 js学习 157阅读 2018-01-15 14:59:21 举报

今天同事写的项目出了个小bug,让我帮忙找找原因。她项目中用的是React和Ant Design。当用React遍历出多个Ant Design中的Upload组件的时候,随意删除任一个Upload时出现了bug。简化版的代码如下:
javascript 代码

运行程序后,依次点击上传图片后,当点击删除时,倒着删除没有问题,从中间和从开头删问题出现了,出现了类似塌方的效果,要删除的Upload元素下面的Upload的元素下面的红框中的内容没有了。。。。

React中使用map遍历元素时key为index遇到的坑
什么问题呢,好神奇?找了半天也没有看出原因来,后来发现将map遍历中的key={index}改为key={item}就能正常显示了。

这里我们来说说React中key的作用。

key是一个字符串,用来唯一标识同父同层级的兄弟元素。当React作diff时,只要子元素有key属性,便会去原v-dom树中相应位置(当前横向比较的层级)寻找是否有同key元素,比较它们是否完全相同,若是则复用该元素,免去不必要的操作。

来,我们举个栗子:
html 代码

现在React就知道了,新增了key为"0"的元素,而"1"与"2"仅仅移动了位置。key必须是字符串类型,它的取值可以用数据对象的某个唯一属性,或是对数据进行hash来生成key。

由此我们知道了导致上面bug的原因。
html 代码

当我们删除中间的元素时,state中的arr变成了[0, 2]
此时代码生成的Dom树如下
html 代码

React发现key为1,2的元素的item都变了,将会修改两者的html,而不是移动它们之间的位置。

总结:
当React的render里不设置key 或者key={index} 时,每次新挂载的节点都是0(其他节点能在willreceiveprops中接检测到改变),因为逆序之后,最后一个元素是0,而这个元素的key之前是没有的,所以要新增节点。要实现目标,需要通过在App的render中设置key={arr.length-index}(因为本例的数组简单,设key={item}也可以),告诉react对应的位置不需要重新挂载。

参考链接:
React中key的作用

React中key的必要性与使用

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复