iT邦幫忙

2024 iThome 鐵人賽

DAY 24
0
Modern Web

現在就學React.js 系列 第 24 篇

提升組件的效能-memo - Day24

  • 分享至 

  • xImage
  •  

在 React 中父組件重新渲染時,所有子組件也會重新渲染,即便這些子組件的 props 沒有發生變化。使用 memo 可以避免不必要的渲染,從而提升應用效能。

memo 是通過「記住」組件的渲染結果,當 props 沒有變化時,它會返回先前的渲染結果,避免再次執行渲染操作。

對memo 的使用有概念後,透過兩個範例來更加理解它的使用與好處吧!

範例一:未使用 memo 的情況

在這個範例中,有一個父組件 App,內部包含一個 TodoItem 子組件。即便 TodoItem 組件的 props 沒有改變,每次父組件 App 重新渲染時,TodoItem 還是會跟著被重新渲染。


import { useState } from 'react'

// 定義 Todo 列表項目
const TodoItem = ({ todo }) => {
  console.log('Rendering Todo:', todo)
  return <p>{todo}</p>
}

const App = () => {
  const [count, setCount] = useState(0)
  const [todos, setTodos] = useState(['Learn React'])

  const increment = () => {
    setCount(c => c + 1)
  }

  const addTodo = () => {
    setTodos(t => [...t, 'New Todo'])
  }

  return (
    <div>
      <div>
        <h2>My Todos</h2>
        {todos.map((todo, index) => (
          <TodoItem key={index} todo={todo} />
        ))}
        <button onClick={addTodo}>Add Todo</button>
      </div>
      <hr />
      <div>
        Count: {count}
        <button onClick={increment}>+</button>
      </div>
    </div>
  )
}

export default App

在這範例中,按下「Count +」按鈕,即便 todos 沒有變化,TodoItem 組件還是會重新渲染,這會影響效能,特別是在列表項目非常多的情況下。

範例二:使用 memo 進行優化

使用 React.memo 來解決這個問題。當 TodoItem 的 props 沒有變化時,它不會重新渲染。

import { useState, memo } from 'react'

// 定義 Todo 列表項目,並使用 memo 來優化
const TodoItem = memo(({ todo }) => {
  console.log('Rendering Todo:', todo)
  return <p>{todo}</p>
})

const App = () => {
  const [count, setCount] = useState(0)
  const [todos, setTodos] = useState(['Learn React'])

  const increment = () => {
    setCount(c => c + 1)
  }

  const addTodo = () => {
    setTodos(t => [...t, 'New Todo'])
  }

  return (
    <div>
      <div>
        <h2>My Todos</h2>
        {todos.map((todo, index) => (
          <TodoItem key={index} todo={todo} />
        ))}
        <button onClick={addTodo}>Add Todo</button>
      </div>
      <hr />
      <div>
        Count: {count}
        <button onClick={increment}>+</button>
      </div>
    </div>
  )
}

export default App

範例說明:

  • TodoItem 使用 memo:透過 memo,TodoItem 組件只有在其 props 改變時才會重新渲染。當按下「Count +」按鈕時,count 的狀態變化不會影響 TodoItem,因為 todos 陣列沒有改變,因此避免了不必要的渲染。

使用 memo 的注意事項

  1. 僅適用於純函數組件:

    memo 只適用於純函數組件,組件依賴於 props,而且不會修改外部狀態或引發副作用。

  2. 謹慎使用場景:

    雖然 memo 可以提升效能,但過度使用會增加程式的複雜性。對於渲染成本較低的組件,可能不需要用 memo 進行優化,避免適得其反。

  3. props 比對成本:

    memo 使用 Object.is 來比較 props 是否變化。這個比對過程本身會產生一定的成本,對簡單的組件,渲染成本可能低於 memo 的比對成本,這時反而不應使用 memo。

結論

memo 是 React 可以用來優化組件效能的工具,當發現某些組件在不必要的情況下被多次重新渲染,不妨考慮使用 memo 來記住組件的渲染結果,從而避免重複渲染並提升效能吧!

後記

本文將會同步更新到我的部落格

黃禎平 – Medium


上一篇
用useMemo優化效能 - Day23
下一篇
useCallback的使用時機 - Day25
系列文
現在就學React.js 共 31 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言