在 React 之中,useMemo 是一個非常實用且能優化效能的 Hook。簡單來說,它的核心功能就是「快取」,也就是幫你把複雜運算的結果存起來,避免重複執行沒必要的計算。
要理解它為什麼能提升效率,我們需要先來看看 React 的運作機制。
為什麼需要 useMemo?
在網頁運作時,只要元件的狀態(State)或屬性(Props)發生改變,React 就會重新渲染該元件。重新渲染意味著元件內部的所有程式碼,都會從上到下重新執行一次。
想像一下,如果你的元件內有一個需要處理上萬條資料的排序函式,每次畫面一有風吹草動,這個排序函式就要重新跑一次,這會消耗極大的瀏覽器運算資源,導致畫面出現卡頓。
useMemo 就是為了解決這個問題而誕生的。
useMemo 的運作原理
useMemo 的基本語法如下:
JavaScript
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
它接收兩個參數:
- 一個帶有回傳值的函式,裡面放置你需要進行的複雜運算。
- 一個陣列,稱為「相依陣列」(Dependency Array)。
它的工作流程非常聰明:
1. 記憶結果
當元件第一次渲染時,useMemo 會執行內部的函式,並把算好的結果存到記憶體中。
2. 比對相依陣列
當元件重新渲染時,useMemo 會去檢查相依陣列裡面的變數(例如上面的 a 和 b)有沒有發生改變。
3. 決定是否重新計算
- 如果
a和b的值跟上一次一模一樣,useMemo就會直接從記憶體拿取上一次算好的結果,完全跳過內部的運算函式。 - 只有當
a或b的值改變了,它才會重新執行運算,並更新記憶體裡的暫存答案。
為什麼這樣可以提升效率?
我們用一個生活中的例子來比喻:
假設老師每天都會考你一題非常複雜的數學題。
- 沒有使用 useMemo 的情況:你每天早上拿到題目,就算題目跟昨天完全一樣,你還是老老實實地在計算紙上從第一步算到最後一步,花了 20 分鐘才寫出答案。
- 使用了 useMemo 的情況:你發現題目沒變,於是直接翻開昨天的筆記本,把寫在上面的答案抄上去,只花了 2 秒鐘。只有當老師換了新題目,你才會重新動筆計算。
在程式裡也是一樣。透過快取機制,useMemo 幫瀏覽器省去了大量重複的 CPU 計算時間,讓網頁反應變得更加流暢。
什麼時候該用 useMemo?
雖然 useMemo 很好用,但這並不代表所有地方都應該加上它。因為「把資料存進記憶體」以及「每次比對相依陣列」本身也需要消耗微小的效能。
以下是適合使用的情境:
- 處理大量資料的運算:例如高達數千筆資料的過濾(Filter)、排序(Sort)或複雜轉換。
- 避免不必要的子元件渲染:當你把一個物件或陣列當作 Props 傳給子元件時,因為 JavaScript 每次重新渲染都會產生新的物件記憶體位址,會導致子元件誤以為資料變了而跟著重新渲染。這時候用
useMemo把物件固定住,就能阻止子元件浪費效能。
如果只是簡單的加減乘除或少數資料的處理,直接讓 React 重新計算即可,不需要刻意使用 useMemo。