You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 18:45:20