React效能優化之React.memo、useMemo和useCallback

語言: CN / TW / HK

前言

我們在使用React開發過程中經常會遇到父元件引入子元件的情況,在不做任何優化處理的時候,往往會造成子元件不必要的重複渲染。看下面一個簡單的例子

``` // 例子1:這種情況下,每次父元件更新count值的時候,子元件也會重複渲染

function Child(props){ console.log('子元件渲染') return(

{props.title}
) } function Parent(){ const [count, setCount] = useState(1); return(
count:{count}
) }

複製程式碼 ```

React.memo

1、React.memo為高階元件,它和React.PureComponent挺相似的

2、用法:React.memo(component, Func),第一個引數是自定義元件,第二個引數是一個函式,用來判斷元件需不需要重新渲染。如果省略第二個引數,預設會對該元件的props進行淺比較

// 改造例子1:這種情況下,Child的props經淺比較無變化,則不重複渲染 function Child(props){ console.log('子元件渲染') return( <div>{props.title}</div> ) } const NewChild = React.memo(Child, (prevProps, nextProps) => { // 自定義對比方法,也可忽略不寫 // return true 則不重新渲染 // return false 重新渲染 }) function Parent(){ const [count, setCount] = useState(1); return( <div> <NewChild title="我是子元件" /> <button onClick={() => setCount(count+1)}>add</button> <div>count:{count}</div> </div> ) } 複製程式碼

然而在某些情況下,光靠React.memo包裹子元件,子元件還是會進行不必要的重複渲染更新,這時useMemo和useCallback則可以進行更細粒度的效能優化。看以下這個例子

``` // 例子2 function Child({title, onChangeTitle}){ console.log('子元件渲染') return( <>

{title.value}

) } const NewChild = React.memo(Child);

function Parent(){ const [count, setCount] = useState(1); const [title, setTitle] = useState('我是子元件'); const onChangeTitle = (text) => { setTitle(text) } return(

count:{count}
) } 複製程式碼 ```

這種情況下,每次父元件更新的時候,子元件的title和onChangeTitle值都會生成新的記憶體地址,所以即使title沒改變,子元件也會重新渲染,memo失效

useMemo

第一次渲染時執行,快取變數,之後只有在依賴項改變時才會重新計算記憶值

useCallback

第一次渲染時執行,快取函式,之後只有在依賴項改變時才會更新快取

``` //改造例子2 function Child({title, onChangeTitle}){ console.log('子元件渲染') return( <>

{title.value}

) } const NewChild = React.memo(Child);

function Parent(){ const [count, setCount] = useState(1); const [title, setTitle] = useState('我是子元件'); const onChangeTitle = useCallback((text) => { setTitle(text) },[]) const memoTitle = useMemo(() => ({value: title}), [title]) return(

count:{count}
) } 複製程式碼 ```

總結

1、useMemo和useCallback用法差不多,都是在第一次渲染的時候執行,然後在依賴項改變時再次執行,不同點在於,useMemo返回快取的變數useCallback返回快取的函式

2、在實際的業務元件開發過程中,肯定比上面舉出的例子要複雜的多得多,因而造成不必要的重複渲染的影響因素也會有很多,我們需要好好利用React.memo、useMemo和useCallback等來優化元件,同時也不要盲目使用

\ 作者:ssssjherr\ 連結:https://juejin.cn/post/7078881777506320397\