歡迎來到我們 React 學習之旅的第十天。今天我們要來聊聊如何讓你的 React 應用程式接起腿後,跑得更快、更順暢。我們將介紹幾個超級實用的效能優化工具:memo
、useMemo
和 useCallback
。
想像一下,如果你的 React 應用程式是一間餐廳。如果每次客人點餐,廚師都要重新準備所有的食材,那這間餐廳肯定會忙翻天。效能優化就像是幫廚師準備好常用的食材,讓他們可以更快地做出美味的料理。
React.memo
是一個高階組件,它可以幫助我們「記住」某個組件,除非它的 props 改變,否則不會重新渲染。
來看個例子:
import React, { memo } from 'react';
interface EmployeeProps {
name: string;
title: string;
}
const Employee: React.FC<EmployeeProps> = memo(({ name, title }) => {
console.log(`${name} 重新渲染了!`);
return (
<div className="employee">
<h3>{name}</h3>
<p>{title}</p>
</div>
);
});
export default Employee;
在這個例子中,除非 name
或 title
改變,否則 Employee
組件不會重新渲染。這就像是餐廳裡的常客,服務生記住了他們的常點餐點,不用每次都重新問。
useMemo
可以幫我們記住複雜計算的結果。除非依賴的值改變,否則不會重新計算。
import React, { useMemo } from 'react';
interface User {
id: number;
name: string;
age: number;
}
const UserStats: React.FC<{ users: User[] }> = ({ users }) => {
const averageAge = useMemo(() => {
console.log('計算平均年齡...');
return users.reduce((sum, user) => sum + user.age, 0) / users.length;
}, [users]);
return <div>平均年齡: {averageAge.toFixed(2)}</div>;
};
export default UserStats;
這就像是餐廳裡的特殊調味料,廚師會事先調配好,除非食譜改變,否則不需要每次都重新調配。
useCallback
可以幫我們「記住」一個函數。這在把函數作為 props 傳遞給使用 React.memo
的子組件時特別有用。
import React, { useCallback, useState } from 'react';
const TodoList: React.FC = () => {
const [todos, setTodos] = useState<string[]>([]);
const addTodo = useCallback((newTodo: string) => {
setTodos(prevTodos => [...prevTodos, newTodo]);
}, []);
return (
<div>
<h2>待辦事項</h2>
<TodoInput onAdd={addTodo} />
<ul>
{todos.map((todo, index) => (
<li key={index}>{todo}</li>
))}
</ul>
</div>
);
};
export default TodoList;
這就像是餐廳裡的招牌菜製作方法,除非食譜改變,否則廚師不需要每次都重新學習如何製作。
雖然這些工具很好很強大,但不要過度使用。每次使用 memo
、useMemo
或 useCallback
,React 都需要做額外的工作來比較值是否改變。如果比較的成本比重新渲染還高,那反而會適得其反。
就像餐廳不會為了每一道菜都準備特製的調味料一樣,我們也不需要為每個組件或函數都使用這些優化技巧。只在真正需要的地方使用它們。
讓我們來看一個實際的例子,如何優化一個購物車組件:
import React, { useMemo, useCallback } from 'react';
interface Product {
id: number;
name: string;
price: number;
}
interface CartProps {
products: Product[];
}
const CartItem: React.FC<Product> = memo(({ name, price }) => (
<li>{name} - NT${price}</li>
));
const Cart: React.FC<CartProps> = ({ products }) => {
const totalPrice = useMemo(() => {
console.log('計算總價...');
return products.reduce((sum, product) => sum + product.price, 0);
}, [products]);
const handleCheckout = useCallback(() => {
console.log('結帳處理...');
// 假設這裡有複雜的結帳邏輯
}, []);
return (
<div>
<h2>購物車</h2>
<ul>
{products.map(product => (
<CartItem key={product.id} {...product} />
))}
</ul>
<p>總價: NT${totalPrice}</p>
<button onClick={handleCheckout}>結帳</button>
</div>
);
};
export default Cart;
在這個例子中:
memo
來優化 CartItem
,避免不必要的重新渲染。useMemo
來記住總價的計算結果。useCallback
來記住結帳處理函數。今天我們學習了 React 的幾個重要效能優化工具:memo
、useMemo
和 useCallback
。這些工具就像是幫助我們的 React 應用程式減肥的好幫手,讓它變得更輕盈、反應更快速。
記住,優化是要針對實際需求來做的。不要為了優化而優化,而是要在發現效能問題時,在來尋找優化的方法。
如果想更了解 React 的效能優化,可以查看 React 官方文件中的效能優化章節。