默认渲染行为的问题

在React Component的生命周期中,有一个shouldComponentUpdate方法。这个方法默认返回值是true。

这意味着就算没有改变组件的props或者state,也会导致组件的重绘。这就经常导致组件因为不相关数据的改变导致重绘,这极大的降低了React的渲染效率。比如下面的例子中,任何options的变化,甚至是其他数据的变化都可能导致所有cell的重绘。

//Table Component
{this.props.items.map(i =>
<Cell data={i} option={this.props.options[i]} />
)}

重写shouldComponentUpdate

为了避免这个问题,我们可以在Cell中重写shouldComponentUpdate方法,只在option发生改变时进行重绘。

class Cell extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
if (this.props.option === nextProps.option) {
return false;
} else {
return true;
}
}
}

这样每个Cell只有在关联option发生变化时进行重绘。

使用PureComponent与immutable.js

因为上面的情况十分通用,React创建了PureComponent组件创建了默认的shouldComponentUpdate行为。这个默认的shouldComponentUpdate行为会一一比较props和state中所有的属性,只有当其中任意一项发生改变是,才会进行重绘。

需要注意的是,PureComponent使用浅比较判断组件是否需要重绘

因此,下面对数据的修改并不会导致重绘(假设Table也是PureComponent)

  options.push(new Option())
options.splice(0, 1)
options[i].name = "Hello"

这些例子都是在原对象上进行修改,由于浅比较是比较指针的异同,所以会认为不需要进行重绘。

为了避免出现这些问题,推荐使用immutable.js。immutable.js会在每次对原对象进行添加,删除,修改使返回新的对象实例。任何对数据的修改都会导致数据指针的变化。

其他的陷阱

需要注意的是,还有一些小陷阱需要避免。

  1. Literal Array与Literal Object
{this.props.items.map(i =>
<Cell data={i} options={this.props.options || []} />
)}

若options为空,则会使用[]。[]每次会生成新的Array,因此导致Cell每次的props都不一样,导致需要重绘。解决方法如下:

const default = [];
{this.props.items.map(i =>
<Cell data={i} options={this.props.options || default} />
)}
  1. 内联函数
    函数也经常作为props传递,由于每次需要为内联函数创建一个新的实例,所以每次function都会指向不同的内存地址。比如:
render() {
<MyInput onChange={e => this.props.update(e.target.value)} />;
}

以及:

update(e) {
this.props.update(e.target.value);
}
render() {
return <MyInput onChange={this.update.bind(this)} />;
}

注意第二个例子也会导致创建新的函数实例。为了解决这个问题,需要提前绑定this指针:

constructor(props) {
super(props);
this.update = this.update.bind(this);
}
update(e) {
this.props.update(e.target.value);
}
render() {
return <MyInput onChange={this.update} />;
}

作者:橙子_80c3
链接:https://www.jianshu.com/p/33cda0dc316a
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 
===================
所以根据上述描述,以前在react中,使用箭头函数,虽然方便了函数的编写,但是会造成每次render都会渲染的问题!所以要改成在constructor函数中对函数绑定this。
注意的是,有些时候不可避免的要用到箭头函数或者在render中bind this 比如要传递参数时:
 
<ul>
{
list.map((item,index) => {
return (
<li key={index} onClick={()=>{deleteList(index)} }>{item}</li>
)
})
}
</ul>

注意上面,传递index时,箭头函数前面不要填写index,而在函数里面输入index。因为在函数前面的index相当于event了  onClick ={(index)=>{deleteList(index)}}

<ul>
{
list.map((item,index) => {
return (
<li key={index} onClick={deleteList.bind(this,index) }>{item}</li>
)
})
}
</ul>
 
 
 

PureComponent的作用及一些使用陷阱的更多相关文章

  1. Python进阶-II 参数陷阱、命名空间、嵌套、作用域、闭包

    一.参数陷阱 在使用默认参数时,可能碰见下列情况 def show_args_trap(i, li = []): li.append(100) li[i] = 101 print(li) show_a ...

  2. Java陷阱之assert关键字

    Java陷阱之assert关键字   一.概述   在C和C++语言中都有assert关键,表示断言. 在Java中,同样也有assert关键字,表示断言,用法和含义都差不多.   二.语法   在J ...

  3. ServiceStack.OrmLite中的一些"陷阱"(2)

    注:此系列不是说ServiceStack.OrmLite的多个陷阱,这仅仅个人认为是某一个陷阱(毕竟我踩坑了)而引发的思考. 前文说到了项目需要使用两种不同的数据库语言,虽说前文问题已基本解决了,但是 ...

  4. T-SQL中的一些小陷阱

    1,当心ISNULL函数对你的逻辑引起BUG 有人喜欢或者习惯于(并不代表我推荐,甚至这种写法没有任何好处)用ISNULL处理变量这种方式写查询 比如:select * from TestISNULL ...

  5. C# 中几个小“陷阱”

    每天写代码,偶尔就会有让你抓狂的时候:代码改了千百遍,蓦然回首,Bug就在灯火阑珊处……这里就列举一些容易犯错的几个小地方,以后遇到了其他的,再慢慢添加.   1. 获取程序当前运行路径   情景复现 ...

  6. 转:C/C++中,空数组、空类、类中空数组的解析及其作用

    转自:http://blog.sina.com.cn/s/blog_93b45b0f01015s95.html 我们经常会遇到这些问题: (1)C++中定义一个空类,他们它的大小(sizeof) 为多 ...

  7. ChannelOption.TCP_NODELAY, true->浅谈tcp_nodelay的作用

    在TCP/IP协议中,无论发送多少数据,总是要在数据前面加上协议头,同时,对方接收到数据,也需要发送ACK表示确认.为了尽可能的利用网络带宽,TCP总是希望尽可能的发送足够大的数据.这里就涉及到一个名 ...

  8. [转]AngularJS: 使用Scope时的6个陷阱

    在使用AngularJS中的scope时,会有6个主要陷阱.如果你理解AngularJS背后的概念的话,这6个点其实非常的简单.但是在具体讲述这6个陷阱之前我们先要讲两个其它的概念. 概念1: 双向数 ...

  9. 【JavaScript】JavaScript中的陷阱大集合

    本文主要介绍怪异的Javascript,毋庸置疑,它绝对有怪异的一面.当软件开发者开始使用世界上使用最广泛的语言编写代码时,他们会在这个过 程中发现很多有趣的“特性”.即便是老练的Javascript ...

随机推荐

  1. java 实现简单的链式栈

    package com.my; /** * 链式栈 * @author wanjn * */ public class LinkedStack { private Node head; private ...

  2. :状态模式:GumballMachine

    #ifndef __STATE_H__ #define __STATE_H__ #include <iostream> #include<stdlib.h> using nam ...

  3. 1076 Wifi密码

    下面是微博上流传的一张照片:“各位亲爱的同学们,鉴于大家有时需要使用 wifi,又怕耽误亲们的学习,现将 wifi 密码设置为下列数学题答案:A-1:B-2:C-3:D-4:请同学们自己作答,每两日一 ...

  4. java Dom4j xml 写

    手动拼接xml 并返回 依赖包 <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</ ...

  5. nw.js的localStorage的物理储存位置

    前言 因为在做美团外卖商家端的nw.js壳子项目,需要保证在壳子里面使用localStorage的数据可以持久化保存. 发现nw可以保存,即使删除应用重写打包也可以保存,所以解决了这个需求,但是还是需 ...

  6. BBbacktrace installation

    1: get the installation package https://backtrackbb.readthedocs.io/en/latest/Method.html#overview ht ...

  7. SharePoint Framework 企业向导(九)

    博客地址:http://blog.csdn.net/FoxDave 管理SPFx解决方案的容量 所有部署到租户的SPFx解决方案必须被租户管理员审批通过.这是通过上传SPFx包(.sppkg)到A ...

  8. Ajax 以及 前端JSP页面如何查看数值

    $.ajax({ url: ctx + "/unit/rsdl/qyjy/getDljgCode", type: "post", success: functi ...

  9. <HBase><Scan>

    Overview The Scan operation for HBase. Scan API All operations are identical to Get with the excepti ...

  10. Python Algorithms – chapter3 计数初步

    一些基本递归式的解决方案及其应用实例 主定理的三种情况 排序算法之侏儒排序法 def gnomesort(seq): i = 0 while i < len(seq): if i == 0 or ...