
本文详解如何在 react 中通过 usestate 正确实现增删待办任务功能,避免误删全部任务、状态不同步及 dom 手动操作引发的副作用。
本文详解如何在 react 中通过 usestate 正确实现增删待办任务功能,避免误删全部任务、状态不同步及 dom 手动操作引发的副作用。
在 React 应用中管理动态列表(如待办事项)时,必须遵循“状态驱动 UI”原则:所有视图变更应由 React 状态(如 useState)触发,并通过 JSX 条件渲染或 .map() 动态生成元素,而非直接操作 DOM(如 document.createElement、appendChild 或 remove())。原代码中手动创建和删除 DOM 节点,不仅绕过了 React 的更新机制,还导致 handleDel 无差别遍历并移除所有任务容器,造成“全删”和后续无法添加的问题。
以下是推荐的现代化、可维护的实现方式:
构建 Shopify 嵌入式应用(Embedded App)的开发技能:基于 @shopify/shopify-app-react-router + React Router v7 + Admin API 2026-04。覆盖 shopifyApp 配置、authenticate.admin 的 GraphQL/REST 调用、Webhook 校验、Session 存储、订阅计费、App Bridge 导航、部署,并新增:适用场景判断、安全最佳实践、错误处理与容错、最佳实践、常见问题 FAQ、高级场景。G
✅ 核心改进点
- 使用 useState 统一管理任务数组(tasks),确保状态与 UI 同步;
- 删除 DOM 手动操作,改用 map() 渲染任务项,并为每个删除按钮绑定唯一索引;
- 删除逻辑仅影响目标项,通过 setTasks([...tasks.slice(0, index), ...tasks.slice(index + 1)]) 或更简洁的 filter/splice 方式实现;
- 移除全局变量 taskArr 和 ref 外部副作用(如 document.body.appendChild),避免组件卸载后残留节点。
✅ 完整可运行代码示例
import React, { useState, useRef } from 'react';
import DelIcon from './assets/close-btn.png';
import './styling/home.scss';
function Task(todo) {
this.todo = todo;
}
function Home() {
const [tasks, setTasks] = useState([]);
const inputRef = useRef(null);
const handleAdd = () => {
const value = inputRef.current?.value.trim();
if (!value) return;
const newTask = new Task(value);
setTasks(prev => [...prev, newTask]);
inputRef.current.value = '';
};
const handleDelete = (index) => {
setTasks(prev => prev.filter((_, i) => i !== index));
};
return (
<div id="home-container">
<input
type="text"
ref={inputRef}
maxLength={40}
placeholder="Enter a task..."
/>
<button onClick={handleAdd}>Add</button>
<div className="task-container">
{tasks.length === 0 ? (
<p className="empty-state">No tasks yet. Add your first one!</p>
) : (
tasks.map((task, index) => (
<div className="task-div" key={index}>
<p>{task.todo}</p>
<button
className="delete-btn"
onClick={() => handleDelete(index)}
aria-label={`Delete task: ${task.todo}`}
>
<img src={DelIcon} alt="delete" />
</button>
</div>
))
)}
</div>
</div>
);
}
export default Home;⚠️ 注意事项
- key 必须稳定且唯一:此处使用数组索引 index 是安全的,因为任务只在末尾添加/中间删除,且不涉及排序;若需支持拖拽重排,建议改用唯一 ID(如 uuid)。
- 避免直接修改 state 数组:切勿使用 tasks.splice(index, 1),而应返回新数组(如 filter 或展开运算符)。
- 输入校验不可少:添加空值检查(trim() + !value),防止生成空白任务。
- 无障碍优化:为删除按钮添加 aria-label,提升可访问性。
- 样式隔离:确保 .task-container、.task-div 和 .delete-btn 在 home.scss 中正确定义,避免布局错乱。
通过以上重构,你的待办列表将具备响应式、可预测且符合 React 最佳实践的行为——每次点击删除按钮,仅移除对应任务,且新增任务功能始终可用。

















