停止在 React 元件回撥中使用箭頭函式!

王大冶發表於2024-11-25
  • CSS技巧與案例詳解
  • vue2與vue3技巧合集
  • VueUse原始碼解讀

image.png

在構建 React 應用時,許多開發者都喜歡使用箭頭函式,因為它們簡潔易用。但你知道嗎,在元件回撥中直接使用箭頭函式可能會導致一些效能問題?在本文中,我們將分析這種情況發生的原因,並探討你應該考慮的最佳實踐。

什麼是箭頭函式?

在深入討論最佳實踐之前,我們快速回顧一下箭頭函式。箭頭函式是 ES6 引入的特性,它為 JavaScript 中的函式書寫提供了更簡短的語法。相比使用更冗長的 function 關鍵字,你可以這樣寫:

const add = (a, b) => a + b;

它們是編寫簡潔程式碼的絕佳工具,在 React 元件中尤其有用。例如,你可能經常看到這樣的程式碼:

<Component onClick={() => console.log('Clicked!')}>
  Click me!
</Component>

看起來很簡單?然而,問題在於箭頭函式與 React 的渲染生命週期的互動方式。

避免渲染時的效能缺陷

當你在 React 元件中直接建立函式時,比如在事件處理程式中使用箭頭函式,每次元件渲染時都會建立一個新的函式例項。我們看一個基本示例:

function MyComponent() {
  return (
    <ChildComponent onClick={() => console.log('Clicked!')}>
      Click me!
    </ChildComponent>
  );
}

乍看之下,這似乎無害。但每次 MyComponent 渲染時(由於狀態更新、父元件渲染等),都會建立該箭頭函式的新例項。在以下情況下,這可能會成為問題:

  1. 你的元件頻繁重新渲染:頻繁的重新渲染意味著反覆建立新的函式例項,這可能會效率低下。
  2. 回撥函式作為 prop 向下傳遞:如果你將這個函式作為 prop 傳遞給子元件,可能會導致這些子元件不必要的重新渲染,因為 React 認為它每次都收到了一個新的 prop(即使函式做的事情完全相同)。
  3. 使用 React 的 useCallback 或 useMemo 進行最佳化:使用這些 hooks 時,新的函式例項可能會破壞記憶化,導致比預期更多的渲染。

對於小型應用來說,這可能看起來無關緊要,但隨著應用規模的擴大和元件的增長,這可能會對效能產生明顯影響。

不必要重新渲染的快速示例

假設你有一個帶有專案列表的父元件,並且你為列表中的每個專案渲染一個子元件:

function ParentComponent({ items }) {
  return (
    <div>
      {items.map((item) => (
        <ChildComponent key={item.id} onClick={() => handleClick(item)} />
      ))}
    </div>
  );
}

在這個例子中,每次 ParentComponent 重新渲染時,都會為每個專案建立一個新的箭頭函式,這將導致每個 ChildComponent 也重新渲染,即使 items 和 handleClick 都沒有改變。

當前的最佳實踐是什麼?

為了避免這種效能陷阱並提高元件的整體可讀性,你應該在元件的渲染範圍之外定義回撥函式,並使用 useCallback

使用 useCallback 進行記憶化

如果你使用帶有 hooks 的函式元件,React 提供了 useCallback,它可以讓你對函式定義進行記憶化:

import { useCallback } from 'react';

function MyComponent() {
  const handleClick = useCallback(() => {
    console.log('Clicked!');
  }, []); // 依賴陣列確保只有當依賴項改變時才重新建立函式

  return <ChildComponent onClick={handleClick}>Click me!</ChildComponent>;
}

當將函式作為 props 傳遞給子元件時,這種方法特別有效,因為它透過保持相同的函式引用來避免不必要的重新渲染。

什麼時候可以在回撥中使用箭頭函式?

這並不是說箭頭函式在回撥中完全是邪惡的,應該完全避免使用。它們非常適合快速原型或不會經常渲染的元件。如果你確信效能不會有問題,那麼使用它們是可以的。

但對於頻繁重新渲染的元件,或者在將回撥作為 props 傳遞下去的場景中,最好避免使用內聯箭頭函式。

結論

箭頭函式是 JavaScript 中一個很棒的特性,提供了簡潔性和更清晰的程式碼。但在 React 元件回撥中直接使用它們可能會導致不必要的重新渲染,並且隨著應用程式的增長會帶來效能缺陷。總結一下最佳實踐:

  1. 在渲染範圍之外定義回撥,並在函式元件中使用 useCallback 來記憶化函式。
  2. 注意何時將回撥作為 props 傳遞。

瞭解這些效能陷阱和最佳實踐將幫助你構建更高效的 React 應用程式,使其能夠優雅地擴充套件。祝編碼愉快!

首發於公眾號 大遷世界,歡迎關注。📝 每週一篇實用的前端文章 🛠️ 分享值得關注的開發工具 ❓ 有疑問?我來回答

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

相關文章