React TodoList点击Edit报错:Cannot read properties of undefined (reading 'map')
React TodoList 点击Edit后状态变为undefined的问题分析与修复
问题描述
实现React简易TodoList时,点击Edit按钮触发报错:Cannot read properties of undefined (reading 'map'),调试发现退出reducer作用域后tasks状态变为undefined。
问题根源
在reducer的edit分支中,错误使用了Array.forEach()方法:
case "edit": { const tempObj = state.forEach((item) => { if (item.id === action.id) { return { ...item, isEditMode: !item.isEditMode }; } else return item; }); return tempObj; }
forEach()方法的返回值始终是undefined,当reducer返回这个值时,tasks状态会被直接替换为undefined,后续执行tasks.map()自然触发报错。
修复方案
将forEach()替换为Array.map(),map()会返回全新数组,符合reducer纯函数的要求(返回新状态,不修改原状态):
case "edit": { return state.map((item) => { if (item.id === action.id) { return { ...item, isEditMode: !item.isEditMode }; } return item; }); }
额外优化建议
- 禁止直接修改状态对象
当前代码中直接修改item.task = e.currentTarget.value违反React状态不可变原则,应新增update类型的action,通过dispatch更新任务内容:
// reducer新增分支 case "update": { return state.map(item => { if (item.id === action.id) { return { ...item, task: action.task }; } return item; }); } // 输入框onChange修改为 onChange={(e) => { dispatch({ type: "update", id: item.id, task: e.currentTarget.value }); }}
- 优化ID生成逻辑
使用useRef生成递增ID,避免随机ID重复风险:
const idRef = useRef(0); const idCreator = () => { return idRef.current++; };
内容的提问来源于stack exchange,提问作者Arash Alipoor
相关产品推荐
相关产品推荐

