在 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
的注意事項僅適用於純函數組件:
memo
只適用於純函數組件,組件依賴於 props
,而且不會修改外部狀態或引發副作用。
謹慎使用場景:
雖然 memo
可以提升效能,但過度使用會增加程式的複雜性。對於渲染成本較低的組件,可能不需要用 memo
進行優化,避免適得其反。
props
比對成本:
memo
使用 Object.is
來比較 props
是否變化。這個比對過程本身會產生一定的成本,對簡單的組件,渲染成本可能低於 memo
的比對成本,這時反而不應使用 memo
。
memo
是 React 可以用來優化組件效能的工具,當發現某些組件在不必要的情況下被多次重新渲染,不妨考慮使用 memo
來記住組件的渲染結果,從而避免重複渲染並提升效能吧!
本文將會同步更新到我的部落格