Sitemap

React — UseMemo

5 min readMay 5, 2025

--

要理解這個 hook 有什麼好處,直接看例子最快

import React, { useState } from "react";

interface Item {
id: number;
price: number;
}

const App: React.FC = () => {
const [items] = useState<Item[]>([
{ id: 1, price: 100 },
{ id: 2, price: 200 },
{ id: 3, price: 300 },
]);

const [count, setCount] = useState(0);

// 效能問題示範:每次重新渲染都會重新計算總價
const calculateTotal = () => {
console.log("重新計算總價...");

// 模擬耗時計算
const start = performance.now();
while (performance.now() - start < 100) {
// 故意延遲 100ms
}

return items.reduce((sum, item) => sum + item.price, 0);
};

return (
<div className="p-4">
<h1 className="text-2xl font-bold mb-4">useMemo 效能示範</h1>

<div className="mb-4">
<button
className="bg-blue-500 text-white px-4 py-2 rounded"
onClick={() => setCount((c) => c + 1)}
>
點擊次數: {count}
</button>
</div>

<div className="mt-4">
<p className="text-lg">
商品總價: {calculateTotal()} 元
<br />
<small className="text-gray-500">
(每次點擊按鈕都會重新計算總價,即使商品沒變)
</small>
</p>
</div>
</div>
);
};

export default App;

在這個例子沒有使用 useMemo,就導致了不必要的重新渲染及計算 😢

Get jimmy.dev’s stories in your inbox

Join Medium for free to get updates from this writer.

正確的寫法應該是要相依 items 陣列,只有當 items 改變時才重新計算。

import React, { useState, useMemo } from "react";

interface Item {
id: number;
price: number;
}

const App: React.FC = () => {
const [items] = useState<Item[]>([
{ id: 1, price: 100 },
{ id: 2, price: 200 },
{ id: 3, price: 300 },
]);

const [count, setCount] = useState(0);

// 使用 useMemo 優化:只有當 items 改變時才重新計算
const total = useMemo(() => {
console.log("重新計算總價...");

// 模擬耗時計算
const start = performance.now();
while (performance.now() - start < 100) {
// 故意延遲 100ms
}

return items.reduce((sum, item) => sum + item.price, 0);
}, [items]); // 相依陣列中只有 items,計數器改變時不會重新計算

return (
<div className="p-4">
<h1 className="text-2xl font-bold mb-4">useMemo 效能優化示範</h1>

<div className="mb-4">
<button
className="bg-blue-500 text-white px-4 py-2 rounded"
onClick={() => setCount((c) => c + 1)}
>
點擊次數: {count}
</button>
</div>

<div className="mt-4">
<p className="text-lg">
商品總價: {total} 元
<br />
<small className="text-gray-500">
(使用 useMemo 後,只有商品改變時才會重新計算總價)
</small>
</p>
</div>
</div>
);
};

export default App;

最後整理一下,關於這個 hook 你需要知道的事情 💡

使用時機

  1. 當計算過程耗時較長(如複雜的數據處理、大量計算)
  2. 當計算結果被頻繁使用但輸入數據不常變化
  3. 當需要避免子元件不必要的重新渲染時

相依陣列(Dependency Array)的重要性

  1. 必須正確設定相依陣列 [dependencies]
  2. 只有當相依陣列中的值改變時,才會重新計算
  3. 空陣列 [] 表示只在元件首次渲染時計算一次

--

--

jimmy.dev
jimmy.dev

Written by jimmy.dev

0 followers

Keep going !