iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 25
1
Modern Web

React.js 從 【0】 到【1】推坑計畫 系列 第 25

【Day 25】useCallback - 學會把函式記起來

不知不覺來到第 25 天了,本來預計是要用小專案作結的,沒想到意外的忙碌啊,所以剩下的幾天就決定介紹一些我原本也不熟悉或不常使用的特性,學習的同時也盡量內化並記錄在這裡。

直接來看他的使用方法:

const removeFromCart = React.useCallback(() => {
    dispatch(removeItem(product.id))
}, [product.id]);

等等等等等等等等一下

這跟 useMemo 也有 87% 像了吧?

首先先來釐清一下:

  • useMemo 像是對於“值”的 memorization
  • useCallback 則是對於“函式實體”的 memorization
const dispatch = useDispatch();

const removeFromShoppigCart = () => dispatch(removeProduct(product.id));

return (
    <Button onClick={removeFromShoppingCart}>Delete</Button>
);

帶入一個簡易的範例,寫了一個 removeFromShoppingCart function 用來派發 redux 的 action,再把它以 callback 的形式傳入 客製化的 Button component 中。

這邊先帶出上例的結論給各位思考:

只要上面的 component render ,Button component 就會重新渲染。

有讀者可能會想到,那簡單,我在 Button component 裡實作前幾天教的 shallowCompare 就好啦!
很遺憾,這樣反而使整體效能更差了....

Why?

原因在於 removeFromShoppigCart 其實每次在元件渲染時都是創造了一個新的函式實體出來,對於 Button 來說,每次傳入 callback 的都是一個新的函數,也因次在這做淺比較是沒有意義甚至是多餘的行為。

const removeFromCart = React.useCallback(() => {
    dispatch(removeItem(product.id))
}, [product.id]);

使用 useCallback 後, Button component 只有在 product.id 改變時才會重新渲染囉!

然而 useCallback 並不是隨時使用了都會讓效能提升的,有些狀態下使用反而增加了程式的負擔,這邊就交給各位自行研究使用時機啦!


上一篇
【Day 24】 useRef
下一篇
【Day 26】誰說一定要用別人寫好的 hooks - Custom Hooks
系列文
React.js 從 【0】 到【1】推坑計畫 30

尚未有邦友留言

立即登入留言