[React優化]PureComponent 與 memo 存在的意義

重點

一旦父組件渲染,因此子組件都要跟着渲染,儘管這個子組件並無任何改變。在這種狀況下,這個子組件的渲染就變得多餘。數組

1.失敗案例

舉個例子🌰:bash

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的值,最後卻也跟着從新渲染了!函數

浪費資源!ui

2.嘗試解決

給Child組件改變shouldComponentUpdate生命週期。this

由於沒有接受到父組件的props以及自身也沒有state,因此直接返回false。spa

若是shouldComponentUpdate返回false,那麼就不會觸發該組件的render渲染!code

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,那麼要從新渲染。

相關文章
相關標籤/搜索