iT邦幫忙

2021 iThome 鐵人賽

DAY 29
0
Modern Web

前端日常,每天 React 一下系列 第 29

【Day 28】Hook 08:useCallback

useCallback

如果父元件所傳遞的 props 包含 Object,
則在元件因狀態改變而 re-render 時,
Object 的記憶體位址也會隨之重新分配。

useCallback 則能夠在特定條件下
保留原本的 Object,
防止其記憶體位址參考
因 re-render 而被改變。

因此搭配 React.memo 使用時,
能夠避免因傳入元件的 callback
記憶體位址不同而強迫重新渲染的問題。


用法

const memorizedValue = useCallback(callback, array)
  • callback:一個 function, dependencies array 變動時才會被更新。
  • array:內容發生改變時才重新執行,所有在 callback 中引用的值都應該出現在這個 array 中,否則 useCallback 可能會失效
const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

useCallback 會幫我們記住
callback 函式的記憶體位置,
在 React 元件重新渲染時,
若 dependencies array 中的值沒有被修改,
就沿用上次的 reference。

使用範例

const List = ({getItems}) => {
  const [item, setItems] = useState([])
  useEffect(() => {
    setItems(getItems())
  }, [getItems])
  
  return item.map(item => <span key={item}>{item} , </span>)
}

const App = () => {
  const [number, setNumber] = useState(0);

  // very slow function
  const getItems = useCallback(() => {
    return [number, number + 1, number + 2]
  }, [number])
  
  const changeHandler = e => {
    setNumber(e.target.value)
  }
 
  return (
    <>
        <input type='number' value={number} onChange={changeHandler} />
        <List getItems={getItems} ></List> 
    </>
  )
};

useMemo 與 useCallback

useCallback(fn, depsArr)
等同於
useMemo(() => fn, depsArr)

  • useMemo:返回值是 callback 的返回值 → 得到一個值
  • useCallback:返回值是 callback 本身 → 得到一個函式

參考資料


上一篇
【Day 27】Hook 07:useMemo
下一篇
【Day 29】Hook 09:自定義 Hook(Custom hook)
系列文
前端日常,每天 React 一下30

尚未有邦友留言

立即登入留言