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

React函数组件删除任务后渲染异常:State正确但列表显示错位

问题根因

你的问题完全是列表渲染使用数组下标作为key+子组件内部维护本地状态共同导致的React组件错误复用问题:

  • 你在Tasks组件中遍历tasks渲染Task时,使用了数组下标index作为组件的key属性
  • 当你删除中间位置的任务后,剩余任务的数组下标会整体前移一位,React做虚拟DOM Diff时会认为下标对应的组件仍然存在,直接复用原有组件实例,不会重新创建
  • 而你的Task组件内部的title、id、buckets等状态,仅在组件首次初始化时从props.task取值一次,后续props.task更新时,这些本地状态不会自动同步,导致复用的组件仍然展示旧的任务数据,就出现了「已删除任务保留、最后一个任务消失」的异常表现

解决方案

1. 优先修复key属性(必做)

将Tasks组件中渲染Task的key从数组下标替换为任务的唯一标识,也就是你接口返回的任务id:

// 原来的写法
return <Task key={index} task={task} setReload={setReload} />
// 替换为
return <Task key={task._id} task={task} setReload={setReload} />

修改后React可以通过唯一id正确识别需要删除的组件,不会错误复用其他任务的组件实例。

2. 优化Task组件的状态管理(推荐)

你的Task组件不需要把props.task的所有属性都复制到本地state,直接读取props.task的属性即可,不需要额外维护一套状态,从根源避免props和state不同步的问题:

// 不需要这一堆重复的本地状态
// const [title, setTitle] = useState(task.title)
// const [buckets, setBuckets] = useState(task.buckets)
// 直接用props.task取值即可
<h3 className='task-element task-title'>{task.title}</h3>
<p className='task-element'>{parseBody(task.body)}</p>

如果确实需要编辑功能需要本地状态,要添加useEffect监听props.task的变化,同步更新本地状态:

useEffect(() => {
  setTitle(task.title)
  setBuckets(task.buckets)
  setBody(task.body)
  setId(task._id)
  // 其他需要同步的状态
}, [task])

额外调试提示

你当前代码中useEffect里setTasks(resJson.tasks)之后立刻循环打印tasks,拿到的是更新前的旧值,因为React的setState是异步更新的,调试的时候注意避免被误导。


内容的提问来源于stack exchange,提问作者Dylan Anderson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 01:51:04