我們已經學習了如何使用解構與展開運算子優化語法。今天我們要來看 React 開發中最常出現的三個 JavaScript 陣列高階函數:map、filter 與 reduce。
在 React 的「聲明式 (Declarative)」開發思維中,我們很少使用傳統的 for 迴圈,而是透過這些不修改原陣列(回傳新資料)的高階函數來處理資料與 JSX。
map() 會遍歷陣列中的每一個元素,並將處理後的結果組合成一個長度相同的新陣列。
在 React 中,map() 是將資料陣列轉換為 JSX 元素清單 的唯一首選:
const UserList = ({ users }) => {
return (
<ul>
{users.map((user) => (
// map 適合直接回傳 JSX 元素,記得加上 key
<li key={user.id}>
{user.name} ({user.role})
</li>
))}
</ul>
);
};
filter() 會測試陣列中的每個元素,只保留符合條件(回傳 true)的項目,並回傳一個全新陣列。
在 React 中,它常用於搜尋關鍵字過濾,或是搭配 State 更新來刪除項目:
// 僅渲染角色為 Admin 的使用者
const adminUsers = users.filter((user) => user.role === 'Admin');
return (
<ul>
{adminUsers.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
const [todos, setTodos] = useState([
{ id: 1, text: '學會 JS 核心' },
{ id: 2, text: '學會 React' },
]);
// 使用 filter 產生剔除 targetId 後的新陣列,確保不可變性
const handleDelete = (targetId) => {
setTodos(todos.filter((todo) => todo.id !== targetId));
};
reduce() 透過累加器 (Accumulator) 將陣列轉換成單一值(可以是數字、物件或另一個陣列)。
在 React 中,它常用於計算購物車總價、統計數據,或是將平坦資料轉換為 Grouping 物件:
const cart = [
{ id: 1, name: 'React 課', price: 3000, count: 1 },
{ id: 2, name: 'JS 課', price: 2000, count: 2 },
];
// 計算購物車總金額
const totalPrice = cart.reduce((sum, item) => {
return sum + item.price * item.count;
}, 0); // 0 是初始值 (initialValue)
return <div>總金額:${totalPrice}</div>; // 總金額:$7000
這三個高階函數都不會修改原陣列 (Non-mutating),因此可以串聯呼叫:
const products = [
{ id: 1, name: '無線滑鼠', price: 800, inStock: true },
{ id: 2, name: '機械鍵盤', price: 2500, inStock: false },
{ id: 3, name: '27 吋螢幕', price: 6000, inStock: true },
];
// 鏈式處理:先過濾現貨,再轉換成顯示格式
const displayList = products
.filter((product) => product.inStock) // 1. 篩選有現貨的商品
.map((product) => ({ // 2. 轉換資料結構
id: product.id,
title: product.name,
formattedPrice: `NT$ ${product.price.toLocaleString()}`,
}));
/* 輸出結果:
[
{ id: 1, title: '無線滑鼠', formattedPrice: 'NT$ 800' },
{ id: 3, title: '27 吋螢幕', formattedPrice: 'NT$ 6,000' }
]
*/