iT邦幫忙

2023 iThome 鐵人賽

DAY 19
0
Modern Web

前端開發之那些我會的與我不會的技術系列 第 19

React中的效能優化:了解 useCallback 和 useMemo Hooks

  • 分享至 

  • xImage
  •  

今天這篇文章要來介紹另外兩個hooks,useCallback和useMemo兩個都是用來效能優化的hooks,用法相當類似,都是藉由快取來達到優化的效果。

useCallback

const cachedFn = useCallback(fn, dependencies)

useCallback會需要帶入兩個參數,第一個是function,第二個是相依的變數,然後在第一次元件渲染回傳帶入的第一個參數的function,之後如果相依的變數有變更的時候才會再回傳新的function。這個相依變數有變更,是用Object.is()來進行比較,也就是說如果是物件、陣列或是函式,要是相同的記憶體位置才會被視為相同的。以下是官網給的一個範例,看了範例可能可以更好懂一點,如果productId或是referrer有變更的時候useCallback就會回傳當下渲染的function,如果沒有改變就會回傳第一次渲染的function。在這邊React的作法其實每次渲染的時候還是會產生一個新的function,但如果相依變數沒有變更,就會忽略這個新產生的function,回傳快取的function。

import { useCallback } from 'react';

export default function ProductPage({ productId, referrer, theme }) {
  const handleSubmit = useCallback((orderDetails) => {
    post('/product/' + productId + '/buy', {
      referrer,
      orderDetails,
    });
  }, [productId, referrer]);

useMemo

const cachedValue = useMemo(calculateValue, dependencies)

與useCallback非常類似,一樣帶入兩個function,第一個是function,第二個是相依的變數,差別在於useCallback會回傳整個function,useMemo則是回傳function執行過後的結果。第一次渲染的時候會執行一次帶入的function,再來如果相依變數有變更才會重新執行一次function,不然就會回傳之前執行function快取的值。適用於運算很複雜的情境。

import { useMemo } from 'react';

function TodoList({ todos, tab }) {
  const visibleTodos = useMemo(
    () => filterTodos(todos, tab),
    [todos, tab]
  );
  // ...
}

使用時機

如果只是一般的網站,沒什麼太多的互動,其實也沒有必要使用這些hook來優化,優化效果可能也是有限的。以下官方文件有提到的兩個可能可以使用的情境。

  1. 當useCallback回傳的function會被當作useEffect的相依變數,就可以考慮使用,因為如果沒有使用useCallback快取function,每次回傳的function都會是不一樣的,所以每次都會再執行useEffect。
  2. 當有變數是要帶入memo元件的props,就可以考慮使useCallback或useMemo,可以避免在相依變數沒變更的時候重新渲染memo元件。

個人使用時機

因為我主要是使用air bnb的eslint style,它都會要求使用useMemo。雖然官網文件有說即使所有內容都使用useMemo和useCallback對網頁效能也不會有太明顯的傷害,但是對於code的可讀性可能會變差,對於相依變數每次都會變更的使用這兩個hooks也是沒有必要的。所以綜合以上我將來的使用可能還是會有所節制,畢竟很多時候加上去雖然沒什麼壞處,但是也沒有好處,反而徒增code變得更難維護與閱讀。

參考

https://react.dev/reference/react/useCallback

https://react.dev/reference/react/useMemo


上一篇
Redux與useReducer + useContext:選擇適合你的狀態管理工具
下一篇
了解React中的useRef Hook:特性和應用
系列文
前端開發之那些我會的與我不會的技術31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言