useMemo
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
將“創建”函數和依賴項添加到參數上使用備注,它僅會在某個依賴項改變時才重新計算備忘錄值。這種優化避免在每次渲染時都進行高開銷的計算。
也就是說useMemo可以讓函數在某個依賴項改變的時候才運行,這可以避免很多額外的開銷。舉個例子:
不使用useMemo
function Example() { const [count, setCount] = useState(1); const [val, setValue] = useState(''); const getNum = useMemo(() => { return Array.from({length: count * 100}, (v, i) => i).reduce((a, b) => a+b) }, [count]) return <div> <h4>總和:{getNum()}</h4> <div> <button onClick={() => setCount(count + 1)}>+1</button> <input value={val} onChange={event => setValue(event.target.value)}/> </div> </div>; }
使用useMemo
后,成為count
作為依賴值傳遞進去,此時僅當count
變化時才會重新執行getNum
。
useCallback
const memoizedCallback = useCallback( () => { doSomething(a, b); }, [a, b], );
將內聯變量函數和依賴項替換為參數回調使用,回調返回該變量函數的備注,版本,該變量函數僅在某個依賴項改變時才會更新。當您將函數傳遞給經過優化的並使用引用替代性去避免非必要渲染(例如shouldComponentUpdate)的子組件時,則非常有用。
看起來似乎和useMemo差不多,我們來看看這兩個有什么異同:
useMemo
和useCallback
接收的參數都是一樣,都是在其依賴項發生變化后才執行,都是返回緩存的值,區別在於useMemo
返回的是函數運行的結果,useCallback
返回的是函數。
useCallback(fn,deps)相當於useMemo(()=> fn,deps)
使用場景
頂部上面所說的,當你把某些函數傳遞給經過優化的並使用引用替代性去避免非必要渲染(例如shouldComponentUpdate)的子組件時,則非常有用。而父組件傳遞一個函數給子組件的時候,由於父組件的更新會導致該函數重新生成從而傳遞給子組件的函數引用發生了變化,這就會導致子組件也會更新,而很多時候子組件的更新是沒必要的,所以我們可以通過useCallback
來緩存該函數,然后傳遞給子組件。舉個例子:
function Parent() { const [count, setCount] = useState(1); const [val, setValue] = useState(''); const getNum = useCallback(() => { return Array.from({length: count * 100}, (v, i) => i).reduce((a, b) => a+b) }, [count]) return <div> <Child getNum={getNum} /> <div> <button onClick={() => setCount(count + 1)}>+1</button> <input value={val} onChange={event => setValue(event.target.value)}/> </div> </div>; } const Child = React.memo(function ({ getNum }: any) { return <h4>總和:{getNum()}</h4> })
使用useCallback
之后,僅當count
發生變化時Child
組件才會重新渲染,而val
變化時,Child
組件是不會重新渲染的。
作者:威少_zv
鏈接:https://www.jianshu.com/p/b71e56ea2fda
來源:簡書