使用Array.reduce()按状态分组Todos数组时仅保留单条数据的问题排查
问题分析与解决方案
嘿,你的问题很典型——问题出在你用对象合并的方式处理同状态的 todos,而不是把它们收集到数组里!
错误原因拆解
你当前的reduce回调里写的是:
return { ...acc, [todo.status]: { ...acc[todo.status], ...todo } };
这里每次遇到同状态的todo时,你是用对象扩展语法把新todo覆盖到之前的对象上(比如completed属性每次都会被新的todo对象替换),而不是把todo添加到数组里,所以最后completed只会保留最后一条数据。
修正后的代码
我们需要把每个状态对应的初始值设为空数组,然后每次把当前todo追加到对应数组中:
const todos = [ { id: 'a', name: 'Buy dog', action: 'a', status: 'deleted' }, { id: 'b', name: 'Buy food', tooltip: null, status: 'completed' }, { id: 'c', name: 'Heal dog', tooltip: null, status: 'completed' }, { id: 'd', name: 'Todo this', action: 'd', status: 'completed' }, { id: 'e', name: 'Todo that', action: 'e', status: 'todo' }, ]; const groupedTodos = todos.reduce((acc, todo) => { // 先获取当前状态对应的数组,没有的话就用空数组 const currentItems = acc[todo.status] || []; // 返回新的对象,对应状态的数组追加当前todo return { ...acc, [todo.status]: [...currentItems, todo] }; }, {}); console.log(groupedTodos);
为什么这样可行?
- 初始化的累加器
acc是一个空对象 - 每次处理todo时,先取出该状态已有的数组(如果没有就用
[]) - 用扩展运算符创建新数组,把当前todo加进去,避免修改原数组(保持immutable)
- 最后返回新的累加器对象,确保每个状态对应的都是包含所有同状态todo的数组
运行这段代码后,就能得到你期望的结果:
{ "deleted": [{"id": "a", "name": "Buy dog", "action": "a", "status": "deleted"}], "completed": [ {"id": "b", "name": "Buy food", "tooltip": null, "status": "completed"}, {"id": "c", "name": "Heal dog", "tooltip": null, "status": "completed"}, {"id": "d", "name": "Todo this", "action": "d", "status": "completed"} ], "todo": [{"id": "e", "name": "Todo that", "action": "e", "status": "todo"}] }
内容的提问来源于stack exchange,提问作者asd
相关产品推荐
相关产品推荐

