随着项目的推进,页面组件越来越多,越来越细。当我们在父组件setState时,可能都会导致若干子组件进行无效的render。因此解决这个问题是我们学习的目的。
shouldComponentUpdate做了什么?

使用shouldComponentUpdate可以让React知道当前状态或属性的改变是否不影响组件的输出,默认返回ture,返回false时不会重写render,而且该方法并不会在初始化渲染或当使用forceUpdate时被调用,我们要做的只是这样:
shouldComponentUpdate(nextProps, nextState) {
return this.props.someData === nextProps.someData
}
复制代码
当时我们每次都要写如上的代码是不是很烦,因此React为我们提供了PureComponent
PureComponent
PureComponent与Component几乎完全相同,但PureComponent通过props和state的浅对比来实现 shouldComponentUpate。如果对象包含复杂的数据结构,它可能会因深层的数据不一致而产生错误的否定判断(表现为对象深层的数据已改变视图却没有更新)
import { Component, PureComponent } from 'react'
class Parent extends Component {
state = {
title: '我是改变的内容',
name: '张三'
}
handleChangeTitle() {
this.setState({ title: '我已经改变' })
}
handleChangeName() {
this.setState({ name: '李四' })
}
render() {
return (
<>
<div onClick={this.handleChangeTitle.bind(this)}>{this.state.title}</div>
<div onClick={this.handleChangeName.bind(this)}>改变children的值</div>
<Child name={this.state.name} />
</>
)
}
}
class Child extends PureComponent {
render() {
console.log('child is render....')
return (
<div>我是子组件的名称:{this.props.name}</div>
)
}
}
复制代码
当触发handleChangeTitle方法时,render方法并没有被触发。当触发handleChangeName方法时,render方法被触发,完美,但是如果传给Child的props不是String, Number等这种基本类型,而是类似于Object复杂类型呢?
import { Component, PureComponent } from 'react'
class Parent extends Component {
state = {
title: '我是改变的内容',
user: { name: '张三' }
}
handleChangeTitle() {
this.setState({ title: '我已经改变' })
}
handleChangeName() {
let { user } = this.state
user.name = '李四'
this.setState({ user })
}
render() {
return (
<>
<div onClick={this.handleChangeTitle.bind(this)}>{this.state.title}</div>
<div onClick={this.handleChangeName.bind(this)}>改变children的值</div>
<Child name={this.state.name} />
</>
)
}
}
class Child extends PureComponent {
render() {
console.log('child is render....')
return (
<div>我是子组件的名称:{this.props.user.name}</div>
)
}
}
复制代码
这个时候,我们发现触发handleChangeName时,render并没有触发,界面也没有渲染,why?
这是因为state中user对象的引用并没有改变。有人说,我们在handleChangeName改变user的引用,然后PureComponent判断不就正确了吗?
this.setState({ user: { name: '李四' } })
复制代码
我们工作中,大部分传入的对象可能是这样的user: { name: '张三', age: 26, sex: '南', work: '码畜', ... },这个时候你想改变引用就不太合适了。那我们有啥解决方案呢?
immutable.js
immutable是一种持久化数据。一旦被创建就不会被更改。修改immutable对象的时候,将返回新的immutable,且原数据不会改变。immutable数据实现了结构共享:只会影响你改变的节点以及他的父节点,其他节点共享,从而达到了节省性能的目的。
import { Component, PureComponent } from 'react'
import { fromJS } from 'immutable'
class Parent extends Component {
state = {
title: '我是改变的内容',
user: fromJS({ name: '张三' })
}
handleChangeTitle() {
this.setState({ title: '我已经改变' })
}
handleChangeName() {
let { user } = this.state
user = user.set('name', '李四')
this.setState({ user })
}
render() {
return (
<>
<div onClick={this.handleChangeTitle.bind(this)}>{this.state.title}</div>
<div onClick={this.handleChangeName.bind(this)}>改变children的值</div>
<Child name={this.state.name} />
</>
)
}
}
class Child extends PureComponent {
render() {
console.log('child is render....')
const user = this.props.user.toJS()
return (
<>
<div>我是子组件的名称:{this.props.user.get('name')}</div>
<div>我是子组件的名称:{user.name}</div>
</>
)
}
}
复制代码
happy hacking
相关链接:
immutable: juejin.cn/post/697679…























![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)