登录
React.memo 和 React.PureComponent 功能类似,只不过前者用于函数组件,后者用于类组件。
正常情况,当父组件重新渲染时,其中的子组件也会渲染,即使没有给子组件传 props,或者传的 props 并没有变化。
这一情况导致性能无意义的浪费,正常类组件可以使用 shouldComponentUpdate 钩子方法来判断拦截,但函数组件没有这一功能。
所以,现在可以用 React.memo 包裹函数组件:
见以下三个文件,一个父组件,两个子组件。
父组件 App.js
import React from 'react'
import Home from './pages/Home'
import Banner from './pages/Banner'
function App() {
let [state, setState] = React.useState(10);
return (
<div className="App">
<button onClick={() => setState(state + 1)}>当前值:{state},点击 + 1</button>
<Home/>
<Banner num={state}/>
</div>
);
}
export default App;
子组件 Home.js
import React from 'react';
function Home() {
console.log('Home 渲染')
return <div>Home页</div>
}
export default Home
子组件 Banner.js
import React from 'react';
function Banner() {
console.log('Banner 渲染')
return <div>Banner页</div>
}
export default Banner
当打开页面 -> 点击按钮时,依次打印如下所示:
> 打开页面
# Home 渲染
# Banner 渲染
> 点击按钮
# Home 渲染
# Banner 渲染
> 点击按钮
# Home 渲染
# Banner 渲染
可见,Home 组件明明没有传入 props,也会更新渲染,浪费性能。
此时,父组件不变,两个子组件各只改一行。
子组件 Home.js
- export default Home
+ export default React.memo(Home)
子组件 Banner.js
- export default Banner
+ export default React.memo(Banner)
再次进行操作,依次打印如下所示:
> 打开页面
# Home 渲染
# Banner 渲染
> 点击按钮
# Banner 渲染
> 点击按钮
# Banner 渲染
这次只传了 props 且 props 发生变化了的 Banner 组件更新渲染了。
并且,当父组件更新后,如果传给某个子组件的 props 并没有变化,那么这个子组件也不会更新渲染,这就是 React.memo 的功能。
最后,React.PureComponent 和 React.memo 功能是相同的,只不过是给组件用的。
因为 React.memo 默认情况下其只会对复杂对象做浅层对比,如果想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现。
如下组件,传入 peope 对象,如果只改 people.age 字段,组件不会重新渲染,只有改动了 people.name 才会。
import React from 'react';
function Banner(props) {
let people = props.people
return <div>姓名:{people.name},年龄:{people.age}</div>
}
// 对比函数
function areEqual(prevProps, nextProps) {
console.log(prevProps, nextProps)
if (prevProps.people.name === nextProps.people.name) {
return true
} else return false
}
export default React.memo(Banner, areEqual)