默认渲染行为的问题

在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. Saiku的基本使用介绍(三)

    Saiku的基本使用介绍(这里都是使用Admin用户登录系统) 1.启动安装好的Saiku  ( ./start-saiku.sh ) ,浏览器使用访问系统 http://localhost:8080 ...

  2. STM32之RTC配置与初始化

    void rtc_init() { //让电源和后备寄存器使能 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE) ...

  3. 关于对Access数据库的学习报告

    学习Access数据库的报告 一.前言 一开始我对access一窍不通,甚至不知道它是干什么的,后来经过网上资料的查阅对它略有了解.microsoft office access是由微软发布的关联式数 ...

  4. Oracle 用户 表 表空间之间的关系和管理

    文献地址: https://blog.csdn.net/jmilk/article/details/51599260 https://www.cnblogs.com/roger112/p/768530 ...

  5. Spring学习四

    1先导入 Asject的jar包 2配置文件加入标签 ,并加入 <aop:aspectj-autoproxy proxy-target-class="true">(如果 ...

  6. L299 EST 科技英语翻译-美学取向 (下)

    4. Ordering(有序美) DescriptiveExpositoryArgumentative Chinese: end focus 句尾焦点English: beginning focus ...

  7. Day4作业及默写

    1,写代码,有如下列表,按照要求实现每一个功能 li = ["alex", "WuSir", "ritian", "barry&q ...

  8. 30行python让图灵机器人和茉莉机器人无止尽的瞎扯蛋

    首先注册申请图灵机器人的API: http://www.tuling123.com/ 查看一下API的格式,很简单: { "key": "APIKEY", &q ...

  9. JAVA_关键词01_instanceof的应用

    A instanceof  B: 对象A是否是 B类的一个实例 应用举例:

  10. Netty核心概念

    一个Netty程序始于Bootstrap类,Bootstrap类是Netty提供的一个可以通过简单配置来设置或“引导”程序的一个重要的类.Netty中设计了Handlers来处理特定的"ev ...