构建 React Todo 应用:组件通信与状态管理的最佳实践

Todo 应用虽小,却是检验框架理解深度的"试金石"。它涵盖了状态管理、组件拆分、数据流控制、本地持久化等核心概念。使用 React 构建这样一个应用,不仅能体现函数式编程与组件化思想的优势,更能清晰展示父子组件通信、状态提升与单向数据流 的设计哲学。

状态集中管理:单一数据源原则

React 推崇"状态提升"------将共享状态置于最近的共同父组件中。在 Todo 应用中,所有待办事项 todos 被统一管理在 App 组件内:

复制代码
const [todos, setTodos] = useState(() => {
  const saved = localStorage.getItem('todos');
  return saved ? JSON.parse(saved) : [];
});

通过 useState 的函数式初始化,应用启动时自动从 localStorage 恢复历史数据。这种设计确保了整个应用只有一个"真相来源",避免了状态分散导致的不一致问题。

子组件通信:通过 Props 传递数据与行为

子组件如 TodoInputTodoListTodoStats 均不持有自身状态,而是通过 props 接收数据和操作方法:

复制代码
<TodoInput onAdd={addTodo} />
<TodoList 
  todos={todos} 
  onDelete={deleteTodo}
  onToggle={toggleTodo}
/>
<TodoStats 
  total={todos.length}
  active={activeCount}
  completed={completedCount}
  onClearCompleted={clearCompleted}
/>
  • TodoInput 接收 onAdd 回调,用于提交新任务;
  • TodoList 接收任务列表及删除、切换完成状态的方法;
  • TodoStats 显示统计信息并提供清除已完成项的功能。

这种模式严格遵循单向数据流 :数据自上而下传递,修改请求自下而上传递。子组件无法直接修改 todos,只能调用父组件提供的函数发起变更,确保状态演进的可预测性。

子到父通信:回调函数作为事件通道

React 不支持子组件直接修改父状态,但可通过回调函数实现"事件上报"。例如,TodoInput 在表单提交时调用 onAdd

复制代码
const handleSubmit = (e) => {
  e.preventDefault();
  onAdd(inputValue);
  setInputValue('');
};

onAdd 实际是 App 中定义的 addTodo 函数,它接收文本并生成新任务:

复制代码
 const addTodo = (text) => {
  setTodos([...todos, {
    id: Date.now(),
    text,
    completed: false
  }]);
};

类似地,TodoList 中的复选框和删除按钮分别触发 onToggleonDelete,将用户操作转化为对中心状态的更新请求。这种机制解耦了 UI 与逻辑,使组件更专注于自身职责。

兄弟组件通信:间接通过父组件协调
TodoInputTodoListTodoStats 是兄弟关系,彼此无直接引用。它们的数据同步完全依赖父组件 App 的协调:

  • TodoInput 添加新任务,App 更新 todos
  • todos 作为 props 传递给 TodoListTodoStats
  • 二者自动重新渲染,显示最新内容。

这种"间接通信"看似绕路,实则保证了数据流的清晰与可追踪。任何状态变化都源于明确的父级更新,极大降低了调试复杂度。

本地持久化:副作用中的数据同步

为防止页面刷新丢失数据,应用需将 todos 同步至 localStorage。这属于典型的副作用操作,由 useEffect 处理:

复制代码
 useEffect(() => {
  localStorage.setItem('todos', JSON.stringify(todos));
}, [todos]);

每当 todos 发生变化(依赖项 [todos] 触发),该副作用自动执行,将最新状态写入存储。这种声明式写法将持久化逻辑与业务逻辑分离,保持主渲染路径的纯净。

样式与用户体验:Stylus 与条件渲染

项目采用 Stylus 预处理器编写样式,配合 React 的条件类名实现动态 UI:

复制代码
<li className={todo.completed ? 'completed' : ''}>

当任务完成时,添加 completed 类,应用删除线等视觉反馈。同时,TodoStats 仅在存在已完成项时显示"清除"按钮:

复制代码
 {completed > 0 && <button onClick={onClearCompleted}>Clear Completed</button>}

这种细粒度的控制提升了界面的响应性与友好度。

总结

这个 Todo 应用虽功能简单,却完整体现了 React 的核心思想:组件化、单向数据流、状态集中管理与副作用隔离 。通过将状态置于顶层、通过 Props 传递数据与回调、利用 useEffect 处理持久化,代码结构清晰、逻辑内聚、易于扩展。无论是初学者理解 React 原理,还是团队建立开发规范,此类实践都提供了坚实的基础。掌握这些模式,便能在更复杂的业务场景中游刃有余地构建健壮、可维护的前端应用。

原文: https://juejin.cn/post/75917028

相关推荐
lichenyang45316 分钟前
从零开始构建 React 文档系统 - 完整实现指南
前端·javascript·react.js
比特森林探险记17 分钟前
Hooks、状态管理
前端·javascript·react.js
landonVM22 分钟前
Linux 上搭建 Web 服务器
linux·服务器·前端
css趣多多25 分钟前
路由全局守卫
前端
AI视觉网奇1 小时前
huggingface-cli 安装笔记2026
前端·笔记
比特森林探险记1 小时前
组件通信 与 ⏳ 生命周期
前端·javascript·vue.js
2301_792580001 小时前
xuepso
java·服务器·前端
海绵宝龙1 小时前
Vue中nextTick
前端·javascript·vue.js
天生欧皇张狗蛋1 小时前
前端部署path问题
前端
H_z_q24012 小时前
Web前端制作一个评论发布案例
前端·javascript·css