React+Redux待办列表CheckTodoItem触发后prevstate与nextstate相同
问题原因与修复方案:Redux状态更新后prevState与nextState一致
你的问题根源是违反了Redux的不可变(Immutable)更新原则——在Reducer里直接修改了原state的引用类型数据,导致prevState和nextState共享同一个数组引用,所以Redux Logger显示两者完全一致,同时React组件也不会触发重新渲染。
问题代码分析
- ADD_TODO_ITEM 分支:使用
state.todoList.push(Todo)直接修改原数组,虽然最后返回了{...state},但todoList还是原来的数组引用。 - CHECK_TODO_ITEM 分支:直接修改
state.todoList[objIndex].isCheck = true,修改了原数组内对象的属性,同样没有创建新的引用。
只有DELETE_TODO_ITEM分支的写法是正确的,因为filter返回了全新的数组。
修复后的Reducer代码
const initialState = { todoList: [ { todo: "workout" , isCheck: false}, { todo: "home work" , isCheck: false}, { todo: "pay bils" , isCheck: false}, { todo: "visit ali" , isCheck: false}, { todo: "Buying household items" , isCheck: false}, ], } const todoListReducer = ( state = initialState , action ) => { switch ( action.type ) { case "ADD_TODO_ITEM": const Todo = { todo: action.payload, isCheck: false, }; // 创建新数组,避免修改原state return{ ...state, todoList: [...state.todoList, Todo] } case "DELETE_TODO_ITEM": const newTodoList = state.todoList.filter( item => item.todo !== action.payload) return { ...state, todoList: newTodoList, } case "CHECK_TODO_ITEM": // 映射数组,找到目标项时返回新对象,其余项保持原样 const updatedTodoList = state.todoList.map(item => { if (item.todo === action.payload) { return {...item, isCheck: true} } return item }) return{ ...state, todoList: updatedTodoList } default : return state } } export default todoListReducer
关键说明
- 对于数组:使用
[...原数组, 新项](添加)、filter(删除)、map(更新某一项)等方法返回全新数组,不能直接用push、splice、pop等修改原数组的方法。 - 对于对象:修改属性时要返回
{...原对象, 要修改的属性: 新值},不能直接修改原对象的属性。
这样修改后,Redux就能正确检测到状态变化,Logger会显示prevState和nextState的差异,组件也会正常触发重新渲染。
内容的提问来源于stack exchange,提问作者ali.t
相关产品推荐
相关产品推荐

