当父组件状态更新后子组件未重新渲染,往往并非 react 机制失效,而是数据结构不一致(如属性名错误)导致子组件读取不到预期字段,从而渲染空内容或静默失败。
当父组件状态更新后子组件未重新渲染,往往并非 react 机制失效,而是数据结构不一致(如属性名错误)导致子组件读取不到预期字段,从而渲染空内容或静默失败。
在您实现的 Todo 应用中,TaskApp 作为父组件通过 useState 管理任务列表,并将 tasks 数组作为 prop 传递给 TaskList 子组件。逻辑上,每次调用 setTasks 后,TaskList 应该接收新数组并重新渲染——React 确实会这么做,但前提是子组件能正确访问到渲染所需的数据字段。
问题根源在于:初始任务数据使用的是 text 字段(如 { id: 10, text: "Visit Paris", done: false }),而新增任务时却误写为 task: text:
// ❌ 错误写法:字段名不一致{ id: nextId++, task: text, // ← 这里应为 text,不是 task done: false}
这导致新增任务对象缺少 text 属性,而 TaskList 组件在 map 中始终尝试访问 task.text:
{tasks.map((task) => ( <div className="task" key={task.id}> {task.text} {/* ← 此处读取 task.text,但新增项只有 task.task */} </div>))}
因此,新增项渲染为空(undefined),看似“未更新”,实则是渲染了空内容。React DevTools 显示状态已更新,印证了父组件状态变更有效、子组件也确实重渲染了——只是因字段名错误,无法显示任何文本。
✅ 正确修复方式是统一字段命名:
function handleAddTask(text) { setTasks((prevTasks) => [ ...prevTasks, { id: nextId++, text, // ✅ 直接使用解构赋值,语义清晰 done: false } ]);}
? 关键提醒:React 的 re-render 触发条件是 props 或 state 发生引用变化(新数组/新对象)。本例中 setTasks 返回了新数组,满足触发条件;真正阻碍视觉更新的是数据契约断裂(initial tasks 与 new task 字段不一致),属于逻辑一致性问题,而非 React 生命周期或 Hooks 使用问题。
此外,建议启用严格模式(Strict Mode)并配合 ESLint 的 react/prop-types 或 TypeScript,可提前捕获此类字段不匹配风险。保持数据结构契约统一,是构建可维护 React 应用的基础前提。