前言
最近开始学习React,跟着Kent学,有很多干货,这里分享memo的使用方法
一、背景
1.1 React lifecycle
React的lifecycle如下
→ render → reconciliation → commit
↖ ↙
state change
其中
"render"
phase: 调用React.createElement创建React element"reconciliation"
phase: 对比之前以及新的element"commit"
phase: 如果需要的话跟新DOM
DOM的更新是很慢的,React就是通过控制必要的DOM跟新来提高速度的
那么,一个React组件的跟新取决于以下几个原因
- 组件的props改变
- 组件的内部state改变
- 组件中读取context内容的改变
- 父组件re-render
但是,React组件的跟新并不意味着这个组件有必要跟新,memo
的出现就是告诉React在那些条件下组件是需要跟新的
二、example
2.1 用法
用法其实很简单,就是把组件通过memo包裹起来就好了,使用如下
Component = React.memo(Component)
但是简单的包裹其实是不能确保是真正提高了性能的,这时候需要借助React DevTools
2.2 react-dev-tool
这里需要下下载React DevTools的插件,然后点Profiler
,准备好要测试的组件的环境,点击左上角的录制⏺按钮录制,完成录制后再点击,就能捕获到组件被redner的情况
![Screen-Shot-2021-02-20-at-12-12-27-pm](https://i-blog.csdnimg.cn/blog_migrate/e34322588d8ce8f6134966f11439d2c5.png)
2.3 使用memo
根据2.1,使用memo包裹组件,再次测试性能,可以发现Memu下面边灰色了,也就是说ListItem组件没有被渲染,同时可以对比上图看出来,App组件的渲染时间变成了0.4ms,对比memo前的1.9ms有了明显的进步,可以说明这里的memo使用是正确的
2.4 memo的第二个参数
2.1中的memo只传了一个参数,那就是component本身,如果不传第二个参数的话,会默认做两次props的浅对比,用户其实可以自定义props怎么变化才需要re-render组件
这里不妨假设Component有两个properties,property_A以及property_B
那么 下面两种写法是等价的
//pass one argument
Component = React.memo(Component)
//pass two arguments
Component = React.memo(Component, (prevProps, nextProps) => {
if (prevProps.property_A !== nextProps.property_A) return false
if (prevProps.property_B !== nextProps.property_B return false
return true
})
但是如果用户有更多的对比条件,那么久可以重写第二个参数的方法,比如
Component = React.memo(Component, (prevProps, nextProps) => {
if (prevProps.property_A !== nextProps.property_A) return false
if (prevProps.property_A !== nextProps.property_A) {
//logic...
return false
}
return true
})
2.5 最佳实践
对于使用memo
来说,最好其props的属性是Primitive Values,也就是最好不要传引用值,这样React就可以主动对比,不需要用户写memo
的第二个参数,手动对比两次props属性
总结
memo的用法其实笔记简单,重点在于能够使用React DevTools分析需要使用memo的组件并且分析memo之后的性能