React 效能瓶頸怎麼辦?用 useMemo 加速你的組件渲染!

作者: Calpa Liu
字數:1623
出版:2025 年 4 月 8 日
React 組件卡頓、重新渲染太慢?本文深入解析 useMemo 的使用方式與實戰案例,幫你解決效能瓶頸,打造流暢的 React 應用體驗。

useMemo 的基本概念與工作原理

useMemo 是 React 內建的 Hook,專門用於記憶(memoize)計算結果。它能夠緩存函數的返回值,避免在每次渲染時重複執行昂貴的計算。useMemo 接受兩個參數:一個計算函數和一個依賴項陣列。當依賴項保持不變時,React 會直接返回先前緩存的值;只有當依賴項發生變化時,計算函數才會重新執行。

const memoizedValue = useMemo(() => {
  // 進行昂貴的計算
  return computeExpensiveValue(a, b);
}, [a, b]); // 依賴項陣列

在上述代碼中,只有當 a 或 b 改變時,computeExpensiveValue 函數才會被重新調用。這種機制極大地減少了不必要的計算,提高了組件的渲染效率。

useMemo 的主要優勢

優化效能表現

useMemo 的首要優勢是能夠提升應用效能。通過避免重複執行耗時的計算,useMemo 減少了不必要的處理時間,使應用響應更加迅速。

// 未使用 useMemo 的例子
const expensiveCalculation = (num) => {
  console.log("計算中...");
  for (let i = 0; i < 1000000000; i++) {
    num += 1;
  }
  return num;
};

// 使用useMemo的優化版本
const memoizedCalculation = useMemo(() => {
  return expensiveCalculation(count);
}, [count]);

在上例中,只有當 count 變化時,昂貴的計算才會執行,大大提高了效能。

避免不必要的重新渲染

React 組件在狀態或屬性變化時會重新渲染。若渲染過程中包含昂貴的計算,可能導致用戶體驗下降。使用 useMemo 可以避免這種情況,確保只在必要時進行計算。

有效管理衍生數據

在處理從狀態或屬性派生的數據時,useMemo 能確保衍生計算只在依賴項變化時執行,優化了數據處理流程。例如,對列表進行排序或過濾時,使用 useMemo 可以避免在每次渲染時重新處理整個數據集。

提升用戶體驗

通過減少計算開銷和提高響應速度,useMemo 直接改善了用戶體驗。快速的響應和流暢的交互是良好用戶體驗的基礎,而 useMemo 在這方面發揮了重要作用。

useMemo 的實際應用場景

優化耗時計算

useMemo 最典型的應用是優化耗時的計算過程,如複雜的數學運算、大量數據的處理等。

function CalculateFactorial() {
  const [number, setNumber] = useState(1);
  const factorial = useMemo(() => factorialOf(number), [number]);

  // 組件其餘部分
}

在這個例子中,階乘計算只在 number 變化時執行,避免了不必要的重複計算。

數據過濾與排序

當需要對大型數據集進行過濾或排序時,useMemo 能有效提升效能。

function BlogPosts({ posts, searchQuery }) {
  const filteredPosts = useMemo(() => {
    return posts.filter((post) =>
      post.title.toLowerCase().includes(searchQuery.toLowerCase())
    );
  }, [posts, searchQuery]);

  // 組件渲染代碼
}

這裡,只有當 posts 或 searchQuery 變化時,過濾操作才會重新執行。

API 響應緩存

useMemo 可用於緩存 API 響應,避免在每次渲染時重複請求或處理數據。

function UserData({ query }) {
  const apiData = useMemo(() => {
    return fetchDataFromAPI(query);
  }, [query]);

  // 使用 apiData 渲染 UI
}

分頁與數據顯示

在實現分頁功能時,useMemo 可以緩存已加載的頁面數據,提高翻頁時的響應速度。

const paginatedData = useMemo(() => {
  const startIndex = (currentPage - 1) * itemsPerPage;
  const endIndex = startIndex + itemsPerPage;
  return data.slice(startIndex, endIndex);
}, [currentPage, data, itemsPerPage]);

useMemo 與 useCallback 的比較

雖然 useMemo 和 useCallback 都用於優化效能,但它們有明顯的區別:useMemo 返回一個記憶化的值,而 useCallback 返回一個記憶化的函數。

// useMemo 記憶計算結果
const memoizedValue = useMemo(() => computeValue(a, b), [a, b]);

// useCallback 記憶函數本身
const memoizedCallback = useCallback(() => {
  doSomething(a, b);
}, [a, b]);

使用正確的 hook 對應正確的場景是優化 React 應用的關鍵。

最佳實踐與注意事項

使用 useMemo 時,應注意以下幾點:

  1. 不要過度使用:只在處理耗時計算時才使用 useMemo,避免為簡單操作增加不必要的複雜性。

  2. 正確設置依賴項:確保依賴項列表包含計算函數中使用的所有反應性值(如 props、state 等)。

  3. 理解效能影響:在應用變得緩慢時,使用 React Profiler 分析效能瓶頸,有針對性地應用 useMemo。

lodash 的 memoize

在 JavaScript 中,我們也可以使用 lodash 的 memoize 函數來實現類似的記憶化功能。

import _ from "lodash";

// 使用 lodash 的 memoize 函數來優化複雜計算
const memoizedFactorial = _.memoize((n: number): number => {
  if (n <= 1) return 1;
  return n * memoizedFactorial(n - 1);
});

透過使用 memoize,我們可以避免在每次呼叫時都進行耗時的計算,進而提升應用的效能。

React 19 中的效能優化:深入淺出 memo

React 19 保留了廣受歡迎的 memo 函式,為開發者提供了強大的效能優化工具。memo 的核心功能是避免函式型組件在 props 保持不變時進行不必要的重新渲染,特別適用於那些需要頻繁更新但大部分 props 保持穩定的場景。

memo 的基本使用

在 React 19 中,memo 的基本語法保持不變:

const MemoizedComponent = memo(MyComponent);

這樣簡單的包裝就能讓 React 跳過對 MyComponent 的重新渲染,除非其 props 發生變化。

自定義比較邏輯

對於更精細的控制,開發者可以提供自定義的比較函式:

const MemoizedComponent = memo(MyComponent, (prevProps, nextProps) => {
  return prevProps.id === nextProps.id && prevProps.name === nextProps.name;
});

這個例子中,只有當 id 或 name 改變時,組件才會重新渲染。

memo 與 Server Components

React 19 的一大亮點是對 Server Components 的完整支持。memo 在這個新架構中扮演著重要角色,能夠顯著減少客戶端的渲染負擔,提升應用整體效能。

最佳實踐

  1. 純粹組件:memo 最適合用於純粹的函式組件,即渲染輸出完全由 props 決定的組件。
  2. 與 useCallback 配合:在傳遞函式作為 props 時,搭配 useCallback 使用可以進一步優化效能。
  3. 適度使用:不要過度使用 memo。對於簡單的組件或經常變化的組件,memo 可能會引入不必要的複雜性。
  4. 效能測試:使用 React DevTools Profiler 來衡量 memo 的實際效能提升。

React 19 中的 memo 不僅保留了其強大的優化能力,還在新的架構下展現出更卓越的效能。透過正確使用 memo,開發者可以顯著提升 React 應用的響應速度和整體用戶體驗。

結論

useMemo 是 React 中優化效能的強大工具,通過記憶化計算結果,避免不必要的重複計算,顯著提升應用效能。在處理耗時計算、大型數據集過濾排序、API 響應緩存等場景中,useMemo 能發揮重要作用。合理使用 useMemo,結合對 React 渲染機制的深入理解,能幫助開發者構建高效、流暢的 React 應用。

然而,開發者也需謹慎使用 useMemo。過度使用可能導致代碼複雜性增加,反而影響應用的可維護性。因此,建議在實際開發中權衡效能提升與代碼複雜度,只在確實需要的地方應用 useMemo。

最後,隨著 React 的不斷發展,效能優化策略也在不斷演進。開發者應持續關注 React 的最新動態,並根據具體應用場景選擇最適合的優化方法。useMemo 作為 React 工具箱中的重要一員,將繼續在前端效能優化中扮演關鍵角色。

想跟上前端開發的最新技術與實戰分享嗎?立即訂閱本站,掌握 React、Vue、TypeScript 等趨勢!
關於 Calpa

Calpa 擅長使用 TypeScriptReact.jsVue.js 建立 Responsive Website。

他積極參與開源社區,曾在 2019 年的香港開源大會上擔任講者,提供工作經驗和見解。此外,他也在 GitHub 上公開分享個人博客程式碼,已獲得超過 300 顆星星和 60 個分支的支持。

他熱愛學習新技術,並樂意分享經驗。他相信,唯有不斷學習才能跟上快速演變的技術環境。

熱門文章

最新文章