Redux Reducer数据过滤异常求助:待办应用编辑删除逻辑问题
嘿,我一眼就看到你这两个Reducer case里的问题了,这就是为啥你会遇到无限层级树结构和删除失效的情况:
1. EDIT_TODO_BUCKET 的循环引用问题
你把 filteredData 直接赋值为 state.data[action.payload.id],这就相当于把待办桶对象本身塞给了它自己的一个属性——这会导致循环引用!因为这个待办桶里现在多了个 filteredData,而这个 filteredData 又是它自己,里面又包含 filteredData,无限套娃下去,Redux DevTools自然会显示无限层级的结构。
另外,你这个case的逻辑也偏离了“编辑待办桶”的初衷:现在的代码只是给目标桶加了个有问题的 filteredData,根本没处理实际要编辑的内容(比如桶的名称、描述这些payload里的字段)。而且如果你的需求是“获取ID为1的待办桶数据”,这个逻辑根本不该放在Reducer里修改状态——Redux的最佳实践是用Selector在组件里获取指定ID的数据,而不是把过滤后的数据存在state里(会造成状态冗余)。
2. DELETE_TODO_BUCKET 根本没执行删除操作
你现在的代码只是把原 state.data 复制了一份,然后又把要删除的ID对应的对象原样放回了新对象里——等于啥都没改!正确的删除应该是从 data 对象里移除这个ID对应的键。
修正后的代码示例
修正编辑逻辑(同时移除错误的循环引用)
假设你的 action.payload 包含 id 和要更新的字段(比如 updates 对象):
case EDIT_TODO_BUCKET: { // 先判断目标桶是否存在,不存在就直接返回原状态 const targetBucket = state.data[action.payload.id]; if (!targetBucket) return state; return { ...state, data: { ...state.data, [action.payload.id]: { ...targetBucket, // 只更新需要修改的字段,比如payload里的updates ...action.payload.updates // 如果确实需要存过滤后的数据,要提取核心字段,比如: // filteredData: { id: targetBucket.id, name: targetBucket.name } // 但更推荐用Selector在组件里获取,而不是存在state里 } } }; }
修正删除逻辑
两种实现方式,选你习惯的就行:
// 方式1:用delete操作符 case DELETE_TODO_BUCKET: { const newData = { ...state.data }; delete newData[action.payload.id]; return { ...state, data: newData }; } // 方式2:用对象解构更优雅 case DELETE_TODO_BUCKET: { const { [action.payload.id]: _, ...newData } = state.data; return { ...state, data: newData }; }
额外建议
如果你的需求是“根据ID获取待办桶数据”,别在Reducer里处理,写个Selector函数就行:
// 在selector文件里 export const getTodoBucketById = (state, bucketId) => { return state.data[bucketId]; }; // 在组件里使用 const bucket = useSelector(state => getTodoBucketById(state, 1));
这样既符合Redux的设计原则,又不会造成状态冗余和循环引用的问题。
内容的提问来源于stack exchange,提问作者Vin

