美文网首页
[React优化]PureComponent 与 memo 存在

[React优化]PureComponent 与 memo 存在

作者: 伐樱大魔 | 来源:发表于2020-02-21 17:03 被阅读0次

    重点

    一旦父组件渲染,所以子组件都要跟着渲染,尽管这个子组件并没有任何改变。在这种情况下,这个子组件的渲染就变得多余。

    1.失败案例

    举个例子🌰:

    
    class Child extends Component {
        render() {
            console.log('Child Render!');
            return (
                <div>
                    hello Child!
                </div>
            );
        }
    }
    
    class Father extends Component {
        state = {
            count: 1
        }
    
        render() {
            console.log('Father Render!');
            return (
                <div>
                    <div>count: {this.state.count}</div>
                    <button onClick={() => this.setState((state) => ({count: state.count + 1}))}>up 1</button>
                    <Child/>
                </div>
            );
        }
    }
    
    export default Father;
    

    当点击按钮的时候,改变了父组件的state的值,父组件理所当然的会重新渲染,但是子组件并没有使用父组件的state的值,最后却也跟着重新渲染了!

    浪费资源!

    2.尝试解决

    给Child组件改变shouldComponentUpdate生命周期。

    因为没有接受到父组件的props以及自身也没有state,所以直接返回false。

    如果shouldComponentUpdate返回false,那么就不会触发该组件的render渲染!

    class Child extends Component {
        shouldComponentUpdate(nextProps, nextState, nextContext) {
            return false;
        }
    
        render() {
            console.log('Child Render!');
            return (
                <div>
                    hello Child!
                </div>
            );
        }
    }
    

    所以我们可以自定义这个shouldComponentUpdate生命周期来控制组件是否渲染。

    但是每次这样写着都很麻烦,于是PureComponent就出世了!

    所以PureComponent就用来解决子组件的不必要渲染问题!

    3.如何使用PureComponent

    class Demo extends PureComponent{
        ...
    }
    
    class Demo extends React.PureComponent{
        ...
    }
    

    根据上面的例子🌰:

    class Child extends PureComponent {
        render() {
            console.log('Child Render!');
            return (
                <div>
                    hello Child!
                </div>
            );
        }
    }
    
    class Father extends Component {
        state = {
            count: 1
        }
    
        render() {
            console.log('Father Render!');
            return (
                <div>
                    <div>count: {this.state.count}</div>
                    <button onClick={() => this.setState((state) => ({count: state.count + 1}))}>up 1</button>
                    <Child/>
                </div>
            );
        }
    }
    
    export default Father;
    

    点击按钮的时候,发现只有父组件渲染了,子组件没有渲染!

    4.memo-函数组件中的PureComponent

    PureComponent只能class用,因为函数组件没有shouldComponentUpdate生命周期!

    但是函数组件也是会随着父组件的渲染而渲染的。

    memo出世!

    上面的例子🌰:

    const Child = () => {
        console.log('Child Render!')
        return <div>hello child</div>
    }
    
    const MemoChild = memo(Child);
    
    class Father extends Component {
        state = {
            count: 1
        }
    
        render() {
            console.log('Father Render!');
            return (
                <div>
                    <div>count: {this.state.count}</div>
                    <button onClick={() => this.setState((state) => ({count: state.count + 1}))}>up 1</button>
                    <MemoChild/>
                </div>
            );
        }
    }
    

    5.PureComponent与memo的特点

    1.浅对比

    就是他们的对于props和state的比较是浅对比

    浅对比:对象就对比他们的内存地址,只要内存地址一致,就不重新渲染,反之,对象的内存地址不一致,就渲染!

    所以当面对修改对象数值的时候最好创建一个新对象重新赋值,这样能够起到渲染的作用!

    2.memo里用了useState/useContext

    memo对函数组件里面的useState/useContext是不起效的。

    意思是context更新了,尽管用了memo,该函数组件依旧会重新渲染。

    3.memo中的“shouldComponentUpdate”

    首先,memo里是没有shouldComponentUpdate这个生命周期的,只是有一个类似的作用。

    memo这个函数可以传递两个参数,一个是我们的组件,一个是类似shouldComponentUpdate这种判断是否渲染的方法。

    memo(ChildComponent,()=>{...})
    

    不过,值得注意的是,这个方法与shouldComponentUpdate相反:如果返回的是true,那么表示不重新渲染,如果返回的是false,那么要重新渲染。

    相关文章

      网友评论

          本文标题:[React优化]PureComponent 与 memo 存在

          本文链接:https://www.haomeiwen.com/subject/rozcqhtx.html