当前位置: 首页 > news >正文

一篇文章告诉你React里为什么不能用index作为key

文章首发于github博客

之前在写react的时候,当我们做map循环的时候,当我们没有一个唯一id来标识每一项item的时候,我们可能会选择使用index

data.map((item, index) => {
    return <li key={index}>{item}</li> 
})
复制代码

但是其实当你使用index来作为唯一key的时候,其实是由一个大坑的,什么坑呢?必须坑了你才知道,来看下面的这种情况:

class App extends React.Component{
	constructor(props) {
		super(props)
		this.state = {
			list: [{id: 1,val: 'aa'}, {id: 2, val: 'bb'}, {id: 3, val: 'cc'}]
		}
	}

	click() {
		this.state.list.reverse()
		this.setState({})
	}
	splice() {
		this.state.list.splice(1,1)
		this.setState({})
	}

	render() {
		return (
            <ul>
                <div onClick={this.splice.bind(this)}>delete</div>
                <div onClick={this.click.bind(this)}>reverse</div>
                {
                	this.state.list.map(function(item, index) {
                		return (
                            <Li key={index} val={item.val}></Li>
                		)
                	}.bind(this))
                }
            </ul>
		)
	}
}

class Li extends React.Component{
	constructor(props) {
		super(props)
	}
	componentDidMount() {
		console.log('===mount===')
	}
	componentWillUpdate(nextProps, nextState) {
		console.log('===update====')
	}
	render() {
		return (
            <li>
                {this.props.val}
                <input type="text"></input>
            </li>
		)
	}
}
复制代码

页面渲染好了之后,3个input输入框依次输入1,2,3: 当我们用index作为key的时候,点击reverse会发现,input输入框还是1,2,3顺序显示,但是这并不符合我们的预期,控制台中此时打印的也是update; 当我们用对象中的id作为key的时候,点击reverse,此时神奇的事情发生了,input输入框变成了3,2,1,符合我们的预期,控制台此时打印的也是update;

为什么会这样呢?

当我们传入index作为key时,此时的key为0,1,2, 当我们点击reverse重新排序后,index传进去的key还是0,1,2,此时react比较key=0时,发现只需要更新子节点的值就可以,于是只把item替换成了cc,而input则相反, 当我们传入id作为index的时候,,点击reverse后,此时的key变成了3,2,1,根据react的diff算法,react还是能分辨出只需要移动子节点即可完成更新,因此input也随之变化。

那说了这么多,其实对于index作为key我们是不推荐的,除非你能够保证他们不会发生变化。

参考文献 index as a key is an anti-pattern, 有问题可以在博客下方留言,感谢star

相关文章:

  • 阿武老师百搭傲娇句式
  • LaTeX模板(二)
  • java可重入锁(ReentrantLock)的实现原理
  • React Native声明属性和属性确认
  • JavaScript深入之词法作用域和动态作用域
  • 竞赛回忆录
  • 简单团队-爬取豆瓣电影TOP250-需求分析
  • JS实现简单的MVC模式开发小游戏
  • 虚拟就Ubuntu 14.0.4 安装配置jenkins
  • 大数据学习(2)HDFS文件管理
  • Mac 10.12安装截图工具Jietu
  • Centos 搭建Mysql-Proxy 读写分离
  • 【小白学云计算】10分钟搭建一台web服务器!(就是快!)
  • [docker]docker网络-直接路由模式
  • SQL 简介
  • 《Javascript高级程序设计 (第三版)》第五章 引用类型
  • 【翻译】Mashape是如何管理15000个API和微服务的(三)
  • 03Go 类型总结
  • co.js - 让异步代码同步化
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • java 多线程基础, 我觉得还是有必要看看的
  • Mac 鼠须管 Rime 输入法 安装五笔输入法 教程
  • Protobuf3语言指南
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • Python进阶细节
  • RxJS: 简单入门
  • yii2中session跨域名的问题
  • 程序员该如何有效的找工作?
  • 第2章 网络文档
  • 构建工具 - 收藏集 - 掘金
  • 如何进阶一名有竞争力的程序员?
  • 使用权重正则化较少模型过拟合
  • 用 Swift 编写面向协议的视图
  • 怎样选择前端框架
  • 字符串匹配基础上
  • 我们雇佣了一只大猴子...
  • ​HTTP与HTTPS:网络通信的安全卫士
  • (1)Android开发优化---------UI优化
  • (16)Reactor的测试——响应式Spring的道法术器
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (力扣)1314.矩阵区域和
  • (十五)devops持续集成开发——jenkins流水线构建策略配置及触发器的使用
  • (四)Android布局类型(线性布局LinearLayout)
  • (轉)JSON.stringify 语法实例讲解
  • 、写入Shellcode到注册表上线
  • .“空心村”成因分析及解决对策122344
  • .NET 2.0中新增的一些TryGet,TryParse等方法
  • .NET Core 控制台程序读 appsettings.json 、注依赖、配日志、设 IOptions
  • .NET Core 中的路径问题
  • .net web项目 调用webService
  • .Net 代码性能 - (1)
  • .net反混淆脱壳工具de4dot的使用
  • .net利用SQLBulkCopy进行数据库之间的大批量数据传递
  • .net中的Queue和Stack