React+Redux应用中Reducer添加元素后State异常变为4且出现todos.map is not a function错误的问题排查
解决Redux Reducer添加元素后State变为数值且map报错的问题
我一眼就看出问题出在你使用Array.push()的方式上,这既违反了Redux的不可变更新原则,又因为push()本身的特性把你的state变成了数字,直接导致了todos.map is not a function错误。
问题根源拆解
push()返回的是数组长度,不是新数组
你写的newTodos = newTodos.push(action.payload),这里push()方法执行后会返回数组的新长度,而不是修改后的数组本身。所以触发ADD_TODO后,你的state就从数组变成了一个数值(比如你看到的4,应该是之前几次操作后累计的数组长度)。直接修改了原state
newTodos = state是引用赋值,这时候newTodos和state指向同一个数组,修改newTodos就等于修改了原state,这完全违反了Redux要求的state不可变原则——Reducer必须是纯函数,不能直接修改传入的state。
修复后的Reducer代码
要正确添加元素,你需要创建一个新数组,而不是修改原数组。推荐用这两种方式:
方式1:使用扩展运算符(最常用)
export const reducer = (state = todos, action) => { switch (action.type) { case ADD_TODO: // 创建原数组的浅拷贝,再添加新元素 return [...state, action.payload]; case DELETE_TODO: // 后续逻辑这里补充 return state; case UPDATE_TODO: // 后续逻辑这里补充 return state; default: return state; } };
方式2:使用concat()方法
case ADD_TODO: // concat返回新数组,不会修改原数组 return state.concat(action.payload);
为什么这样有效?
- 扩展运算符
[...state]会复制原数组的所有元素,生成一个全新的数组,再把action.payload添加到末尾,返回这个新数组作为新的state。 concat()方法同样会返回一个包含原数组元素和新元素的新数组,不会对原state造成任何修改。
这样你的state始终保持数组类型,组件里的todos.map()就能正常执行了。
内容的提问来源于stack exchange,提问作者Siddhesh
相关产品推荐
相关产品推荐

