shouldComponentUpdate
和React.PureComponent
是类组件中的优化方式,而React.memo
是函数组件中的优化方式。
1. PureComponent
PureComponent
通过prop
和state
的浅比较
来实现shouldComponentUpdate
,当prop
或state
的值或者引用地址
发生改变时,组件就会发生更新。- 而
Component
只要state
发生改变, 不论值是否与之前的相等,都会触发更新。
class ComponentDiffPure extends PureComponent {
constructor() {
super();
this.state = { text: 'true' };
}
changeState = () => {
this.setState({ text: 'false' });
};
render() {
console.log('pure-render');
return (
<div>
<button onClick={this.changeState}>Click</button>
<div>{this.state.text}</div>
</div>
);
}
}
2. shouldComponentUpdate
React
提供了生命周期函数shouldComponentUpdate()
,根据它的返回值(true | false),判断 React 组件是否更新shouldComponentUpdate
方法接收两个参数nextProps
和nextState
- 一般我们在
shouldComponentUpdate
中进行更深层次的更新控制
shouldComponentUpdate (nextProps, nextState) {
return true
}
2.1 forceUpdate
- 当明确知道父组件
Parent
修改了引用类型的数据(子组件的渲染依赖于这个数据) - 此时调用
forceUpdate()
方法强制更新
子组件, - 注意,forceUpdate()会跳过子组件的
shouldComponentUpdate()
。 - 不推荐使用
2.2 immutable
Immutable
则提供了简洁高效的判断数据是否变化的方法,只需===
和is
比较就能知道是否需要执行 render()Immutable.js
是 Facebook 在 2014 年出的持久性数据结构的库,持久性指的是数据一旦创建,就不能再被更改,任何修改或添加删除操作都会返回一个新的 Immutable 对象
import { is } from 'immutable'
shouldComponentUpdate (nextProps = {}, nextState = {}) => {
return !(this.props === nextProps || is(this.props, nextProps)) ||
!(this.state === nextState || is(this.state, nextState))
}
3. React.memo
React.memo() 文档地址:https://reactjs.org/docs/react-api.html#reactmemo
- 在函数组件中, React 提供了
React.memo
这个 HOC(高阶组件) React.memo()
可以支持指定一个参数React.memo
仅检查props
变更。如果函数组件被React.memo
包裹,且其实现中拥有useState
或useContext
的 Hook,当context
发生变化时,它仍会重新渲染。
function MyComponent(props) {
/* render using props */
}
function areEqual(prevProps, nextProps) {
/*
return true if passing nextProps to render would return
the same result as passing prevProps to render,
otherwise return false
*/
}
export default React.memo(MyComponent, areEqual);
使用方式很简单,在函数组件之外,在声明一个 areEqual
方法来判断两次 props
有什么不同,如果第二个参数不传递,则默认只会进行 props 的浅比较。
最终 export
的组件,就是 React.memo()
包装之后的组件
4. useMemo
useMemo()
进行细粒度性能优化- 在某些场景下,希望函数组件的
一部分
不要进行 re-render,而不是整个函数组件不要 re-render,也就是要实现局部Pure
功能。 - 使用
useMemo
对依赖属性进行包装
// 根据count变化才会重新返回新的userInfo
const userInfo = useMemo(() => {
return {
age: count,
name: 'hello',
};
}, [count]);
return (
<div>
{number}-{count}
<button onClick={btnHandler}>按钮</button>
<ChildMemo userInfo={userInfo}/>
</div>
)