需要优化的场景
在Hooks为主的React项目中,会有大量的组件通过函数声明。多数情况下,我们不需要对函数组件的渲染进行特殊优化,即使有些重复渲染因不会对体验造成太大影响也被忽略了。 但有些情况下优化就显得很必要,比如如下场景:
const DemoLoader = props => {
const { demoUrl } = props;
return <div className="demoloader">
<iframe src={demoUrl} />
</div>;
};
这里声明了一个函数组件,组件很简单,接受demoUrl props,并作为iframe的src渲染出来。如果这里做了不必要的rerender,iframe就会重新加载,一方面出现白屏,另一方面对服务器增加了一次请求压力。
shouldComponentUpdate
在class组件中,我们可以通过shouldComponentUpdate阻止不必要的rerender:
class DemoLoader extends React.Component {
shouldComponentUpdate(nextProps) {
return nextProps.demoUrl !== this.props.demoUrl;
}
render() {
const { domoUrl } = this.props;
return <div className="demoloader">
<iframe src={demoUrl} />
</div>;
}
}
但在函数组件中,没有shouldComponentUpdate
React.memo
为了解决函数组件中的优化问题,React在16.6版本增加了React.memo。官网文档:reactjs.org/docs/react-…
React.memo是一个高阶组件,类似于React.PureComponent,只不过用于函数组件而非class组件。 如果你的函数组件在相同props下渲染出相同结果,你可以把它包裹在React.memo中来通过缓存渲染结果来实现性能优化。这意味着React会跳过组件渲染,而使用上次渲染结果。
const MyComponent = React.memo(function MyComponent(props) {
/* render using props */
});
React.memo默认只会浅比较props,如果需要定制比较,你可以给第二个参数传入自定义比较函数
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);
和class组件中的
shouldComponentUpdate不同,如果props相同则应返回true,否则返回false。这点二者正好相反。
改写组件
const DemoLoader = React.memo(props => {
const { demoUrl } = props;
return <div className="demoloader">
<iframe src={demoUrl} />
</div>;
}, (prevProps, nextProps) => {
return prevProps.demoUrl === nextProps.demoUrl;
});