React Redux待办列表:对象式数据结构中删除对象的问题
React + Redux 待办事项列表:嵌套对象结构下的删除问题
我正在用React和Redux构建待办事项列表,初始状态必须采用代码中展示的对象嵌套对象结构。作为编程新手,我无法解决从该结构中删除对象的问题。
我尝试过.pop()和.filter()方法,但由于数据是嵌套对象而非数组,这些方法无效。尝试用delete state.data[index]时,控制台抛出错误:cannot update component while rendering other component。移除handleDeleteClick()函数和deleteItem reducer后,其余代码运行正常。相关代码如下:
相关代码
TodoItem 组件
import React, {useState} from 'react'; import { useDispatch } from 'react-redux'; import { editItem, deleteItem, completedItem } from '../store/todoSlice'; const TodoItem = ({ id, content, completed }) => { const dispatch = useDispatch(); // 初始化编辑相关状态 const [edit, setEdit] = useState(false); const [newItem, setNewItem] = useState(content); const [finishedItem, setFinishedItem]= useState(false); // 调用deleteItem reducer的函数 const handleDeleteClick = () => { dispatch(deleteItem({id, content})) } // 调用editItem reducer的函数 const onSubmit = (event) => { event.preventDefault(); dispatch( editItem({id, newItem, completed})); setNewItem(""); setEdit(false); setFinishedItem(false); }; // 调用completedItem reducer的函数 const completedTask = (event) => { event.preventDefault(); dispatch( completedItem({id, content, completed}) ); setFinishedItem(true); }; // 编辑状态下显示编辑输入框 if(edit){ return ( <form> <input id="editInput" value={newItem} onChange= {(e) => setNewItem(e.target.value)} placeholder="Edit your item"/> <button onClick = {onSubmit} type='submit' id="submitButton">ADD</button> </form> ) } // 已完成状态下的展示 if(!edit && finishedItem) { return( <div id="itemSection"> <li id="item">{content} <button onClick= {handleDeleteClick(content)} className="function">DELETE</button> <button onClick={() => setEdit(true)} className="function"> EDIT</button> <button onClick={completedTask} id="completed">COMPLETED</button> </li> </div> ) } // 默认展示状态 return ( <div id="itemSection"> <li id="item">{content} <button onClick={handleDeleteClick()} className="function">DELETE</button> <button onClick={() => setEdit(true)} className="function"> EDIT</button> <button onClick={completedTask}>COMPLETED</button> </li> </div> ); }; export default TodoItem;
todoSlice 状态切片
import { createSlice } from "@reduxjs/toolkit"; export const toDoSlice = createSlice({ name: "todos", // 初始化嵌套对象结构的状态 initialState: { nextId: 2, data: { 1: { content: 'Content 1', completed: false } } }, reducers: { // 添加待办项 addItem: (state, action) => { state.data = { ...state.data, [state.nextId]: { content: action.payload.content, completed: false } } state.nextId += 1; }, // 删除待办项(当前有问题的实现) deleteItem: (state, action) => { const index= action.payload.id; delete state.data[index]; }, // 编辑待办项 editItem: (state, action) => { state.data = { ...state.data, [action.payload.id]: { content: action.payload.newItem, completed: false } } }, // 标记待办项为完成 completedItem: (state, action) => { state.data = { ...state.data, [action.payload.id]: { content: action.payload.content, completed: true } } } } }); export const {addItem, editItem, deleteItem, completedItem} = toDoSlice.actions; export default toDoSlice.reducer;
问题修复方案
1. 核心问题:按钮点击事件错误绑定
你当前的删除按钮写法是直接调用函数,而非传递函数引用:
<button onClick={handleDeleteClick()} className="function">DELETE</button>
组件渲染时就会执行handleDeleteClick(),触发Redux状态更新,这直接导致了"不能在渲染其他组件时更新组件"的错误。
修复方式:传递函数本身(或用箭头函数包裹):
// 不需要传参时,直接传函数引用 <button onClick={handleDeleteClick} className="function">DELETE</button> // 需要传参时,用箭头函数包裹 <button onClick={() => handleDeleteClick(content)} className="function">DELETE</button>
注意!edit && finishedItem分支里的删除按钮也存在同样问题,需要同步修改。
2. Reducer优化(可选,更符合规范)
虽然Redux Toolkit的Immer支持直接用delete修改状态,但更推荐通过创建新对象的方式实现不可变更新,可读性更强:
deleteItem: (state, action) => { const { id } = action.payload; // 解构排除要删除的id,生成新对象 const { [id]: _, ...remainingItems } = state.data; state.data = remainingItems; }
3. 其他冗余状态清理
finishedItem状态完全可以用Redux中的completed字段替代,避免组件内部状态与全局状态不一致:
- 删除
const [finishedItem, setFinishedItem]= useState(false); - 将
!edit && finishedItem改为!edit && completed - 移除
completedTask中的setFinishedItem(true);和onSubmit中的setFinishedItem(false);
内容的提问来源于stack exchange,提问作者Angela
相关产品推荐
相关产品推荐

