一、基礎用法
- useMemo可以保證依賴的值未發生改變的時候,不觸發值改變。
- useCallback可以保證依賴的值未發生改變的時候,不觸發函數引用的改變。
1 //當count變化,sum的值會改變
2 const sum = useMemo(() => { 3 return count + 1; 4 }, [count]); 5 //當count變化,getSum函數會改變
6 const getSum = useMemo(() => { 7 return count + 1; 8 }, [count]);
第二參數含義:
- 不傳數組,每次更新都會重新計算
- 空數組,只會計算一次
- 依賴對應的值,當對應的值發生變化時,才會重新計算
二、應用場景
React的函數式組件在直接使用useState或使用useEffect間接調用useState時,會導致整個函數的重新執行。其中,函數組件包裹的所有的變量、常量、函數都會被重新初始化,相當於props整體更新,所有組件內的子組件重新繪制。但並不是每個子組件都有必要重繪,有的根本沒有變化,這時,就需要使用useMemo和useCallback保證函數組件內常量與函數的唯一性。
1 import React, { useState, memo, useMemo, useCallback } from 'react'
2 const Child = memo((props) => { 3 console.log(props); 4 return ( 5 <div>
6 <input type="text" onChange={props.onChange}/>
7 </div>
8 ) 9 }) 10 const Parent = () => { 11 const [count, setCount] = useState(0) 12 const [text, setText] = useState('') 13 const handleOnChange = useCallback((e) => { 14 setText(e.target.value) 15 },[]) 16 return ( 17 <div>
18 <div>count: {count}</div>
19 <div>text: {text}</div>
20 <button onClick={() => { 21 setCount(count + 1) 22 }}>+1</button>
23 <Child onChange={handleOnChange} />
24 </div>
25 ) 26 } 27 function App() { 28 return <div><Parent /></div>
29 } 30 export default App
上面代碼中,handleOnChange被緩存了下來,盡管父組件更新了,但是拿到的handleOnChange還是同一個,對比useMemo,useMemo緩存的是一個值,useCallback緩存的是一個函數,是對一個單獨的props值進行緩存,memo緩存的是組件本身,是站在全局的角度進行優化。
需要注意的是,useMemo 會在渲染的時候執行,而不是渲染之后執行,這一點和 useEffect 有區別,所以 useMemo 不建議有 副作用相關的邏輯。
useMemo根據依賴的值計算出結果,當依賴的值未發生改變的時候,不觸發狀態改變。一般開發,在向子組件傳遞函數props時,每次 render 都會創建新函數,導致子組件不必要的渲染,浪費性能,這個時候,就是 useCallback 的用武之地了,useCallback 可以保證,無論 render 多少次,我們的函數都是同一個函數,減小不斷創建的開銷。
