react hook性能優(yōu)化:memo,useCallback阻止不必要的重新渲染

在react函數(shù)組件中修改狀態(tài)會(huì)觸發(fā)整個(gè)函數(shù)組件的重載,重載過(guò)程中會(huì)導(dǎo)致函數(shù)中的方法重載和組件重新渲染,這個(gè)過(guò)程中有很多重載和重新渲染是不必要的,我們可以使用memo和useCallback方法來(lái)阻止不必要的性能消耗。

首先定義三個(gè)基礎(chǔ)組件,來(lái)觀察不使用上述方法之前的渲染情況:

image.png

在最外層父組件中聲明count狀態(tài)和更改count的方法setCount,并定義一個(gè)將count重置為0的方法傳遞給Foo組件,當(dāng)我們觸發(fā)count更改時(shí)整個(gè)App函數(shù)都會(huì)重載,重載過(guò)程中會(huì)導(dǎo)致reset方法也被重載,App組件當(dāng)中引入的Foo和Pure組件都會(huì)重新渲染。

image.png

如上圖所示,每次點(diǎn)擊按鈕都會(huì)觸發(fā)兩個(gè)子組件的重新渲染,但是事實(shí)上這兩個(gè)子組件的重新渲染是沒(méi)有必要的。

memo:

memo的作用是在組件重新渲染前確認(rèn)內(nèi)部傳入的組件是否需要重新渲染。
這里將Pure組件用memo方法進(jìn)行嵌套。

image.png

然后再次點(diǎn)擊按鈕更改狀態(tài)觸發(fā)App組件的重新渲染

image.png

可以看到這里再次進(jìn)行點(diǎn)擊,重新渲染的子組件就只有Foo了,由于Pure內(nèi)部沒(méi)有狀態(tài)和屬性更改,memo會(huì)判定該組件無(wú)需重新渲染

useCallback:

useCallback的作用是緩存一個(gè)函數(shù),并傳入相關(guān)的依賴(lài)項(xiàng),只有在依賴(lài)項(xiàng)改變的時(shí)候才會(huì)重載函數(shù)

我們首先給Foo也包裹memo方法

image.png

點(diǎn)擊按鈕更改狀態(tài)觸發(fā)App組件的重新渲染

image.png

發(fā)現(xiàn)即使嵌套了memo,F(xiàn)oo組件還是會(huì)不斷重新渲染,原因是我們從父組件傳入的reset在父組件重載的過(guò)程中也被重載了,新的reset !== 上次傳入的reset,由于屬性發(fā)生了更改,因此被認(rèn)為有必要進(jìn)行重新渲染,這時(shí)就應(yīng)該用useCallback將reset方法進(jìn)行緩存,阻止這種不必要的重新渲染。

image.png

此時(shí)再觸發(fā)狀態(tài)更改

image.png

兩個(gè)組件都只有初始化渲染,不再觸發(fā)重新渲染了。

附代碼:

import React, { memo, useCallback, useState } from "react";

// 最外層父組件
function App() {
  const [count, setCount] = useState(0)

  const reset = useCallback(() => {
    setCount(0)
  }, [])

  return (
    <div className="App">
      <div>{count}</div>
      <button onClick={() => setCount(count + 1)}>add</button>
      <Foo reset={reset} />
      <Pure />
    </div>
  );
}

// 接收函數(shù)
const Foo = memo(function Foo(props) {
  
  console.log('Foo render...');
  return (
    <button onClick={props.reset}>
      reset
    </button>
  )
})

// 純函數(shù)組件
const Pure = memo(function Pure() {
  console.log('pureComponent render...');

  return (
    <div>pureComponent</div>
  )
})

export default App;


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容