汉字魔法师
118.67M · 2026-02-04
你想了解的是在 React + TypeScript 环境下,如何用 reduce 方法处理结构更复杂的对象数据(而非简单数组),我会通过分层拆解 + 实战案例的方式,带你掌握处理复杂对象数据的核心思路和技巧。
reduce 不仅能处理数组,也能通过遍历对象的 key/value 转化为数组后再处理。核心逻辑是:
Object.entries()/Object.values());reduce 的累加器(acc)构建目标数据结构;假设你有一份 “电商订单 + 商品” 的复杂数据,需要用 reduce 完成:
先明确数据结构,避免后续处理时类型混乱:
tsx
import React from 'react';
// 商品信息
interface Product {
id: string;
name: string;
category: string; // 商品分类(电子/服饰/食品)
price: number;
quantity: number; // 购买数量
}
// 订单信息
interface Order {
orderId: string;
userId: string;
userName: string;
createTime: string;
products: Product[]; // 订单包含的商品(嵌套数组)
status: 'paid' | 'unpaid' | 'cancelled'; // 订单状态
}
// 最终统计结果类型
interface OrderStats {
userTotal: Record<string, number>; // 用户名 -> 总消费金额
categorySales: Record<string, number>; // 商品分类 -> 总销量
validOrders: Order[]; // 有效订单(paid + 金额>100)
}
tsx
const ComplexReduceDemo: React.FC = () => {
// 模拟复杂的订单数据(多层嵌套)
const rawOrders: Order[] = [
{
orderId: 'O001',
userId: 'U001',
userName: '张三',
createTime: '2026-01-01',
status: 'paid',
products: [
{ id: 'P001', name: '手机', category: '电子', price: 2999, quantity: 1 },
{ id: 'P002', name: 'T恤', category: '服饰', price: 99, quantity: 2 },
],
},
{
orderId: 'O002',
userId: 'U001',
userName: '张三',
createTime: '2026-01-05',
status: 'unpaid',
products: [
{ id: 'P003', name: '面包', category: '食品', price: 15, quantity: 5 },
],
},
{
orderId: 'O003',
userId: 'U002',
userName: '李四',
createTime: '2026-01-10',
status: 'paid',
products: [
{ id: 'P001', name: '手机', category: '电子', price: 2999, quantity: 2 },
{ id: 'P004', name: '裤子', category: '服饰', price: 199, quantity: 1 },
],
},
];
// 核心:用一次 reduce 完成多维度统计(避免多次遍历)
const stats: OrderStats = rawOrders.reduce((acc, order) => {
// 1. 计算当前订单的总金额(嵌套 products 数组的 reduce)
const orderTotal = order.products.reduce((sum, product) => {
return sum + product.price * product.quantity;
}, 0);
// 2. 统计用户总消费(仅已支付订单)
if (order.status === 'paid') {
acc.userTotal[order.userName] = (acc.userTotal[order.userName] || 0) + orderTotal;
}
// 3. 按商品分类汇总销量(所有订单,无论状态)
order.products.forEach((product) => {
acc.categorySales[product.category] = (acc.categorySales[product.category] || 0) + product.quantity;
});
// 4. 筛选有效订单(已支付 + 金额>100)
if (order.status === 'paid' && orderTotal > 100) {
acc.validOrders.push({ ...order, // 深拷贝避免原数据污染
products: [...order.products]
});
}
return acc;
}, {
userTotal: {},
categorySales: {},
validOrders: [],
} as OrderStats); // 显式指定累加器类型,TypeScript 更友好
// 渲染统计结果
return (
<div style={{ padding: 20 }}>
<h2>复杂对象的 reduce 处理示例</h2>
<div style={{ margin: 10 marginTop: 20 }}>
<h3>1. 用户总消费</h3>
<ul>
{Object.entries(stats.userTotal).map(([user, total]) => (
<li key={user}>{user}:¥{total}</li>
))}
</ul>
</div>
<div style={{ margin: 10 marginTop: 20 }}>
<h3>2. 商品分类销量</h3>
<ul>
{Object.entries(stats.categorySales).map(([category, sales]) => (
<li key={category}>{category}:{sales} 件</li>
))}
</ul>
</div>
<div style={{ margin: 10 marginTop: 20 }}>
<h3>3. 有效订单(已支付 + 金额>100)</h3>
<ul>
{stats.validOrders.map((order) => (
<li key={order.orderId}>
订单{order.orderId}({order.userName}):¥{
order.products.reduce((sum, p) => sum + p.price * p.quantity, 0)
}
</li>
))}
</ul>
</div>
</div>
);
};
export default ComplexReduceDemo;
将组件添加到路由(参考上一篇教程的 routes.ts 配置),启动项目后就能看到复杂数据处理后的结果。
reduce 回调中嵌套另一个 reduce 处理子数组;acc)要初始化为目标结构(如示例中的 OrderStats),并通过 TypeScript 显式指定类型;... 扩展运算符深拷贝(简单场景)或 structuredClone(复杂场景),避免修改原始数据;reduce 中完成所有统计(而非多次遍历数组),提升性能;|| 0 处理累加器中可能的 undefined(如 acc.userTotal[user] || 0),避免 NaN。Object.entries()/Object.values() 将对象转为可遍历数组,再用 reduce 累加器构建目标结构;如果需要处理更复杂的场景(如多层嵌套的树形数据),可以基于这个思路,在 reduce 中增加递归逻辑即可。