我们知道,当组件的props或者state发生变化的时候:React会对组件当前的Props和State分别与nextProps和nextState进行比较,当发现变化时,就会对当前组件以及子组件进行重新渲染,否则就不渲染。有时候为了避免组件进行不必要的重新渲染,我们通过定义shouldComponentUpdate来优化性能。例如如下代码:

class CounterButton extends React.Component {
constructor(props) {
super(props);
this.state = {count: 1};
} shouldComponentUpdate(nextProps, nextState) {
if (this.props.color !== nextProps.color) {
return true;
}
if (this.state.count !== nextState.count) {
return true;
}
return false;
} render() {
return (
<button
color={this.props.color}
onClick={() => this.setState(state => ({count: state.count + 1}))}>
Count: {this.state.count}
</button>
);
}
}

shouldComponentUpdate通过判断props.colorstate.count是否发生变化来决定需不需要重新渲染组件,当然有时候这种简单的判断,显得有些多余和样板化,于是React就提供了PureComponent来自动帮我们做这件事,这样就不需要手动来写shouldComponentUpdate了:

class CounterButton extends React.PureComponent {
constructor(props) {
super(props);
this.state = {count: 1};
} render() {
return (
<button
color={this.props.color}
onClick={() => this.setState(state => ({count: state.count + 1}))}>
Count: {this.state.count}
</button>
);
}
}

大多数情况下, 我们使用PureComponent能够简化我们的代码,并且提高性能,但是PureComponent的自动为我们添加的shouldComponentUpate函数,只是对props和state进行浅比较(shadow comparison),当props或者state本身是嵌套对象或数组等时,浅比较并不能得到预期的结果,这会导致实际的props和state发生了变化,但组件却没有更新的问题,例如下面代码有一个ListOfWords组件来将单词数组拼接成逗号分隔的句子,它有一个父组件WordAdder让你点击按钮为单词数组添加单词,但他并不能正常工作:

class ListOfWords extends React.PureComponent {
render() {
return <div>{this.props.words.join(',')}</div>;
}
} class WordAdder extends React.Component {
constructor(props) {
super(props);
this.state = {
words: ['marklar']
};
this.handleClick = this.handleClick.bind(this);
} handleClick() {
// 这个地方导致了bug
const words = this.state.words;
words.push('marklar');
this.setState({words: words});
} render() {
return (
<div>
<button onClick={this.handleClick} />
<ListOfWords words={this.state.words} />
</div>
);
}
}

这种情况下,PureComponent只会对this.props.words进行一次浅比较,虽然数组里面新增了元素,但是this.props.words与nextProps.words指向的仍是同一个数组,因此this.props.words !== nextProps.words 返回的便是flase,从而导致ListOfWords组件没有重新渲染,笔者之前就因为对此不太了解,而随意使用PureComponent,导致state发生变化,而视图就是不更新,调了好久找不到原因~。

最简单避免上述情况的方式,就是避免使用可变对象作为props和state,取而代之的是每次返回一个全新的对象,如下通过concat来返回新的数组:

handleClick() {
this.setState(prevState => ({
words: prevState.words.concat(['marklar'])
}));
}

你可以考虑使用Immutable.js来创建不可变对象,通过它来简化对象比较,提高性能。
这里还要提到的一点是虽然这里虽然使用了Pure这个词,但是PureComponent并不是纯的,因为对于纯的函数或组件应该是没有内部状态,对于stateless component更符合纯的定义,不了解纯函数的同学,可以参见这篇文章

最新文章

  1. Nginx基础知识之————RTMP模块中的中HLS专题(翻译文档)
  2. 230行实现一个简单的MVVM
  3. return columns.All(new Func&lt;string, bool&gt;(list.Contains));
  4. PHP 正则表达式常用函数使用小结
  5. Android Studio使用OpenCV后,使APP不安装OpenCV Manager即可运行
  6. js循环遍历
  7. Ubuntu 14.04.4 下 scp 远程拷贝提示:Permission denied, please try again. 的解决办法
  8. 【洛谷1640】[SCOI2010]连续攻击游戏
  9. Halcon一维运算相关算子整理
  10. NIO 概述 与 通信实例
  11. android ViewStub简单介绍
  12. bug8 eclipse项目导入到myeclipse时 Target runtime com.genuitec.runtime.generic
  13. 二叉搜索树的后序遍历序列(python)
  14. Java_7 ArrayList集合
  15. rest_framework_api规范
  16. Leetcode模拟题篇
  17. Go语言学习笔记二: 变量
  18. Java 面向对象编程介绍
  19. java基础之常量与变量
  20. 170621 - Android ADB forward端口映射和reverse反向代理 使用笔记

热门文章

  1. Python面向对象(约束,异常处理,md5加密)(五)
  2. centos 服务器配置
  3. Debian 修改时间时区
  4. 【04】图解JSON
  5. C语言常见的函数调用
  6. nginx反向代理+负载均衡+https
  7. scp命令(基于ssh上传文件等)
  8. 被忽视的控件UIToolbar
  9. 使用Apriori算法进行关联分析
  10. tomact和eclipse的关联