React Hook:无用渲染-PureComponent-shouldCompoent-函数组件
过渡技术
1.1无用的渲染
import React from 'react'; class TestC extends React.Component { constructor(props) { super(props); this.state = { count: 0 } } componentWillUpdate(nextProps, nextState) { console.log('componentWillUpdate') } componentDidUpdate(prevProps, prevState) { console.log('componentDidUpdate') } render() { return ( <div > {this.state.count} <button onClick={()=>this.setState({count: 1})}>Click Me</button> </div> ); } } export default TestC; //TestC组件有一个本地状态count,它的初始值是0(state = {count: 0})。当我们点击Click Me按钮时,count的值被设置为1。这时候屏幕的数字将会由0变成1。当我们再次点击该按钮时,count的值还是1, 这时候TestC组件不应该被重新渲染,可是现实是这样的吗? //为了测试count重复设置相同的值组件会不会被重新渲染, 我为TestC组件添加了两个生命周期函数: componentWillUpdate和componentDidUpdate。componentWillUpdate方法在组件将要被重新渲染时被调用,而componentDidUpdate方法会在组件成功重渲染后被调用。 //在浏览器中运行我们的代码,然后多次点击Click Me按钮,你可以看到打印了多次更新操作 //所以即使count被设置相同的值,TestC组件还是会被重新渲染,这些就是所谓的无用渲染。
1.2 shouldComponentUpdate / Pure Component
语法:
//为了避免React组件的无用渲染,我们可以实现自己的shouldComponentUpdate生命周期函数。 //当React想要渲染一个组件的时候,它将会调用这个组件的shouldComponentUpdate函数, 这个函数会告诉它是不是真的要渲染这个组件。 shouldComponentUpdate(nextProps, nextState) { return true } shouldComponentUpdate(nextProps, nextState) { return false } //其中各个参数的含义是: //nextProps: 组件将会接收的下一个参数props //nextState: 组件的下一个状态state //shouldComponentUpdate函数一直返回true,这就告诉React,无论何种情况都要重新渲染该组件。 //这个方法的返回值是false,React永远都不会重新渲染我们的组件。
案例:
用shouldComponentUpdate重写TestC组件:
import React from 'react'; class TestC extends React.Component { constructor(props) { super(props); this.state = { count: 0 } } componentWillUpdate(nextProps, nextState) { console.log('componentWillUpdate') } componentDidUpdate(prevProps, prevState) { console.log('componentDidUpdate') } shouldComponentUpdate(nextProps, nextState) { if (this.state.count === nextState.count) { return false } return true } render() { return ( <div> { this.state.count } <button onClick = { () => this.setState({ count: 1 }) }> Click Me </button> </div> ); } } export default TestC;
1.3 Pure Component
React在v15.5的时候引入了Pure Component组件。React在进行组件更新时,如果发现这个组件是一个PureComponent,它会将组件现在的state和props和其下一个state和props进行浅比较,如果它们的值没有变化,就不会进行更新。要想让你的组件成为Pure Component,只需要extends React.PureComponent
import React from 'react'; class TestC extends React.PureComponent { constructor(props) { super(props); this.state = { count: 0 } } componentWillUpdate(nextProps, nextState) { console.log('componentWillUpdate') } componentDidUpdate(prevProps, prevState) { console.log('componentDidUpdate') } /*shouldComponentUpdate(nextProps, nextState) { if (this.state.count === nextState.count) { return false } return true }*/ render() { return ( <div> { this.state.count } <button onClick = {() => this.setState({ count: 1 }) }> Click Me </button> </div > ); } } export default TestC;
1.4 React.memo
React.memo()是React v16.6引进来的新属性。它的作用和React.PureComponent类似,是用来控制函数组件的重新渲染的。React.memo(...)其实就是函数组件的React.PureComponent
语法:
const Funcomponent = ()=> { return ( <div> I am a Funtional component </div> ) } const MemodFuncComponent = React.memo(FunComponent) //React.memo会返回一个纯化的组件MemoFuncComponent,这个组件将会在JSX标记中渲染出来。当组件的参数props和状态state发生改变时,React将会检查前一个状态和参数是否和下一个状态和参数是否相同,如果相同,组件将不会被渲染,如果不同,组件将会被重新渲染。
案例:
let TestC = (props) => { console.log('Rendering TestC :', props) return ( <div> { props.count } </div> ) } TestC = React.memo(TestC)
函数组件的无用渲染怎么解决?
React.memo
1.React核心开发团队一直都努力地让React变得更快。在React中可以用来优化组件性能的方法大概有以下几种:
-
组件懒加载: React.lazy(...) 和 < Suspense />
-
Pure Component
-
shouldComponentUpdate(...){...}生命周期函数
React16.6加入的另外一个专门用来优化函数组件(Functional Component)性能的方法: React.memo