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

React Todo List删除功能异常:数组未更新且列表未重渲染求助

问题根源

  1. 直接修改props违反React规则:你直接修改了父组件传入的items props,但React中props是只读的,子组件无法修改父组件的状态,这种修改不会触发父组件的状态更新,页面自然不会重渲染。
  2. 内部状态未实际使用:你定义了taskListItem状态,但渲染列表时遍历的仍是原props的items,所以即使更新了内部状态也不会影响页面显示。

解决方案

方案一:父组件维护状态(推荐,符合React数据流)

TodoList的状态通常需要在父组件或全局维护,子组件只负责渲染和触发动作,通过回调通知父组件执行更新。

修改子组件:
interface Props {
  items: string[];
  onDelete: (index: number) => void; // 添加删除回调函数
}

const TaskList = ({ items, onDelete }: Props) => {
  return (
    <>
      <ul className="list-group">
        {items.map((item, num) => {
          // 注意:尽量不用index作为key,若item有唯一标识(如id)优先用它
          return (
            <li className="list-group-item " key={num}>
              <button
                className="btn btn-primary"
                onClick={() => onDelete(num)} // 触发父组件的删除逻辑
              >
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  width="16"
                  height="16"
                  fill="currentColor"
                  className="bi bi-check"
                  viewBox="0 0 16 16"
                >
                  <path d="M10.97 4.97a.75.75 0 0 1 1.07 1.05l-3.99 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425a.267.267 0 0 1 .02-.022z" />
                </svg>
              </button>
              {item}
            </li>
          );
        })}
      </ul>
    </>
  );
};

export default TaskList;
父组件示例(以App组件为例):
import { useState } from 'react';
import TaskList from './TaskList';

const App = () => {
  const [items, setItems] = useState<string[]>(["a", "b", "c", "d", "e"]);
  
  const handleDelete = (index: number) => {
    // 生成新数组,不直接修改原状态
    const newItems = [...items.slice(0, index), ...items.slice(index + 1)];
    setItems(newItems);
  };

  return (
    <div>
      <TaskList items={items} onDelete={handleDelete} />
    </div>
  );
};

export default App;

方案二:子组件自行维护状态(仅适合组件独立使用场景)

如果不需要父组件共享状态,子组件可以把传入的初始值作为内部状态的起点,后续用自身状态管理列表:

interface Props {
  initialItems: string[]; // 明确是初始值,避免和内部状态混淆
}

const TaskList = ({ initialItems }: Props) => {
  const [taskItems, setTaskItems] = useState<string[]>(initialItems);
  
  const deleteItem = (index: number) => {
    const newItems = [...taskItems.slice(0, index), ...taskItems.slice(index + 1)];
    setTaskItems(newItems);
  };

  return (
    <>
      <ul className="list-group">
        {taskItems.map((item, num) => {
          return (
            <li className="list-group-item " key={num}>
              <button
                className="btn btn-primary"
                onClick={() => deleteItem(num)}
              >
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  width="16"
                  height="16"
                  fill="currentColor"
                  className="bi bi-check"
                  viewBox="0 0 16 16"
                >
                  <path d="M10.97 4.97a.75.75 0 0 1 1.07 1.05l-3.99 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425a.267.267 0 0 1 .02-.022z" />
                </svg>
              </button>
              {item}
            </li>
          );
        })}
      </ul>
    </>
  );
};

export default TaskList;

额外注意事项

  • 避免用数组索引作为key:如果每个任务有唯一标识(如ID),优先用标识作为key,防止列表项顺序变化时出现渲染异常。
  • 保持数据不可变性:永远不要直接修改props或state,必须通过setState生成新的数组/对象来更新状态,这样React才能正确检测变化并触发重渲染。

内容的提问来源于stack exchange,提问作者Rb Mohit

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 13:00:36