1. 程式人生 > 實用技巧 >React函式式元件值之useMemo()和useCallback()

React函式式元件值之useMemo()和useCallback()

一、基礎用法

  • 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 多少次,我們的函式都是同一個函式,減小不斷建立的開銷。