React memo介绍与使用
前言介绍之前可以了解下shouldComponentUpdate,React PureComponent。React.memo介绍React.memo 为高阶组件。它与 React.PureComponent 非常相似,但它适用于函数组件,但不适用于 class 组件。如果你的函数组件在给定相同 props 的情况下渲染相同的结果,那么你可以通过将其包装在 React.memo 中调用,以...
前言
介绍之前可以了解下shouldComponentUpdate,React PureComponent。
React.memo介绍
React.memo 为高阶组件。它与 React.PureComponent 非常相似,但它适用于函数组件,但不适用于 class 组件。
如果你的函数组件在给定相同 props 的情况下渲染相同的结果,那么你可以通过将其包装在 React.memo 中调用,以此通过记忆组件渲染结果的方式来提高组件的性能表现。这意味着在这种情况下,React 将跳过渲染组件的操作并直接复用最近一次渲染的结果。
React.memo 仅检查 props 变更。如果函数组件被 React.memo 包裹,且其实现中拥有 useState 或 useContext 的 Hook,当 context 发生变化时,它仍会重新渲染。
默认情况下其只会对复杂对象做浅层对比,如果你想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现。
const MyComponent = React.memo(function MyComponent(props) {
/* 只在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
*/
}
function MyComponent(props) {
/* render using props */
}
export default React.memo(MyComponent, areEqual);
例子:
import React from "react";
function Child({seconds}){
console.log('I am rendering');
return (
<div>I am update every {seconds} seconds</div>
)
};
function areEqual(prevProps, nextProps) {
if(prevProps.seconds===nextProps.seconds){
return true
}else {
return false
}
}
export default React.memo(Child,areEqual)
React.memo原理
其实react.memo的实现很简单,如下:
export default function memo<Props>(
type: React$ElementType,
compare?: (oldProps: Props, newProps: Props) => boolean,
) {
if (__DEV__) {
if (!isValidElementType(type)) {
warningWithoutStack(
false,
'memo: The first argument must be a component. Instead ' +
'received: %s',
type === null ? 'null' : typeof type,
);
}
}
return {
$$typeof: REACT_MEMO_TYPE,
type,
compare: compare === undefined ? null : compare,
};
}
可以看到,最终返回的是一个对象,这个对象带有一些标志属性,在react Fiber的过程中会做相应的处理。
在ReactFiberBeginWork.js中可以看到:
if (updateExpirationTime < renderExpirationTime) {
// This will be the props with resolved defaultProps,
// unlike current.memoizedProps which will be the unresolved ones.
const prevProps = currentChild.memoizedProps;
// Default to shallow comparison
let compare = Component.compare;
compare = compare !== null ? compare : shallowEqual;
if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) {
return bailoutOnAlreadyFinishedWork(
current,
workInProgress,
renderExpirationTime,
);
}
}
根据传入的compare函数比较prevProps和nextProps,最终决定生成对象,并影响渲染效果。
其实就是在实现shouldComponentUpdate生命周期,之前的PureComponent是在class组件中使用,现在的memo是让函数式组件可以实现相同效果。
React.memo使用(适用函数式组件)
React.memo()使用场景就是纯函数组件频繁渲染props
import React, { Component } from 'react'
// 使用React.memo代替以上的title组件,让函数式组件也拥有Purecomponent的功能
const Title=React.memo((props)=>{
console.log("我是title组件")
return (
<div>
标题: {props.title}
</div>
)
})
class Count extends Component {
render() {
console.log("我是条数组件")
return (
<div>
条数:{this.props.count}
</div>
)
}
}
export default class Purememo extends Component {
constructor(props){
super(props)
this.state={
title:'shouldComponentUpdate使用',
count:0
}
}
componentDidMount(){
setInterval(()=>{
this.setState({
count:this.state.count+1
})
},1000)
}
render() {
return (
<div>
<Title title={this.state.title}></Title>
<Count count={this.state.count}></Count>
</div>
)
}
}
更多推荐
所有评论(0)