news 2026/1/28 2:12:44

react中todolist小案例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
react中todolist小案例

Todolist.tsx

import React, { useState } from "react"; // 引入 Redux 相关的 Hooks import { useDispatch, useSelector } from "react-redux"; // 引入刚才定义的 Actions,用于触发状态变更 import { addTodo, removeTodo, toggleCompleted } from "../store/todoList"; // 引入 nanoid 用于生成 ID import { nanoid } from "nanoid"; // 引入 RootState 类型,用于类型推断 import type { RootState } from "../store/index"; // 引入 TodoItemType 类型,用于定义本地状态类型 import type { TodoItemType } from "../store/todoList"; /** * TodoList 函数式组件 * 实现了待办事项的增、删、改(状态切换)功能 */ const TodoList = () => { // --- 本地状态 (Component State) --- // 用于管理输入框的受控组件状态 const [inputValue, setInputValue] = useState(""); // --- Redux 状态与方法 --- // 获取 dispatch 函数,用于向 store 发送指令 const dispatch = useDispatch(); // 从 Redux Store 中选取 todos 数据 // 使用泛型 <RootState> 帮助 TypeScript 推断 state 结构 // 使用 `as TodoItemType[]` 进行类型断言(或者确保 RootState 中的 todos 类型定义正确) const todos = useSelector<RootState>((state) => state.todos) as TodoItemType[]; // --- 事件处理函数 --- /** * 处理添加 Todo 的逻辑 */ const handleAddTodo = () => { // 1. 校验输入是否为空 if (inputValue.trim() !== "") { // 2. 构造新的 Todo 对象 const newTodo: TodoItemType = { id: nanoid(5), // 生成短 ID text: inputValue, completed: false, // 默认未完成 }; // 3. 派发 addTodo Action // 注意:这里传入的是整个 Todo 对象,与 Slice 中定义的 PayloadAction<TodoItemType> 对应 dispatch(addTodo(newTodo)); // 4. 清空输入框 setInputValue(""); } }; /** * 处理删除 Todo * @param id - 要删除的 Todo 的 ID */ const handleRemoveTodo = (id: string) => { // 派发 removeTodo Action // 注意:这里传入的是 { id: 'xxx' },与 Slice 中定义的 PayloadAction<{id: string}> 对应 dispatch(removeTodo({ id })); }; /** * 处理切换完成状态 * @param id - 要切换状态的 Todo 的 ID */ const handleToggleCompleted = (id: string) => { dispatch(toggleCompleted({ id })); }; // --- 渲染 JSX --- return ( <> <h2>Todo List</h2> <div> {/* 双向绑定输入框 */} <input type="text" value={inputValue} // 更新本地状态 onChange={(e) => setInputValue(e.target.value)} placeholder="Enter a new todo" /> {/* 绑定添加事件 */} <button onClick={handleAddTodo}>Add</button> </div> <ul> {/* 遍历从 Redux 获取的列表 */} {todos.map((todo) => ( <li key={todo.id}> {/* 复选框绑定 completed 状态 */} <input type="checkbox" checked={todo.completed} // 触发状态切换 onChange={() => handleToggleCompleted(todo.id)} /> {/* 根据 completed 状态动态添加删除线样式 */} <span style={{ textDecoration: todo.completed ? "line-through" : "none", }} > {todo.text} </span> {/* 删除按钮 */} <button onClick={() => handleRemoveTodo(todo.id)}>Delete</button> </li> ))} </ul> </> ); }; export default TodoList;

todoList.ts

// 引入 createSlice 用于创建切片(包含 action 和 reducer) import { createSlice } from "@reduxjs/toolkit"; // 引入 PayloadAction 类型,用于给 reducer 中的 action 定义 payload 的类型 import type { PayloadAction } from "@reduxjs/toolkit"; // 引入 nanoid 用于生成唯一的 ID import { nanoid } from "nanoid"; // --- 类型定义 --- /** * 定义 Todo 项目的类型 */ export type TodoItemType = { id: string; // 唯一标识符 text: string; // 任务描述文本 completed: boolean; // 标记任务是否已完成 }; // --- 初始状态 --- /** * 定义 Todo 列表的初始状态 * 包含两条示例数据 */ const INIT_STATE: TodoItemType[] = [ { id: nanoid(5), text: "learn redux", completed: false, }, { id: nanoid(5), text: "learn typescript", completed: false, }, ]; // --- Slice 创建 --- /** * 创建 TodoList 的 Slice * Slice 会自动生成对应的 action creators 和 reducer 逻辑 */ export const todoListSlice = createSlice({ name: "todoList", // Action type 的前缀,例如:todoList/addTodo initialState: INIT_STATE, // 初始状态数组 reducers: { /** * 添加 Todo 的 Reducer * @param state - Immer 代理的 Draft 状态,可以直接"修改"或返回新状态 * @param action - 包含 payload (新 Todo 对象) 的动作 */ addTodo: (state, action: PayloadAction<TodoItemType>) => { // 方式一:返回新数组 (不可变更新) // return [...state, action.payload]; // 方式二:使用 Immer 推荐的"直接修改"语法 (底层会自动生产新状态) // 这里我们把新任务添加到数组末尾 state.push(action.payload); }, /** * 删除 Todo 的 Reducer * @param action.payload - 一个包含 id 字段的对象,用于指定删除哪个任务 */ removeTodo: (state, action: PayloadAction<{ id: string }>) => { // 解构出要删除的 ID const { id: removeId } = action.payload; // 查找该 ID 对应的索引 const index = state.findIndex((item) => item.id === removeId); // 如果找到了,使用 splice 直接删除 (Immer 允许这种写法) if (index !== -1) { state.splice(index, 1); } }, /** * 切换任务完成状态的 Reducer * @param action.payload - 一个包含 id 字段的对象,用于指定切换哪个任务 */ toggleCompleted: (state, action: PayloadAction<{ id: string }>) => { const { id: toggleId } = action.payload; // 在数组中查找对应的 Todo 项 const todo = state.find((item) => item.id === toggleId); // 如果找到了,直接取反它的 completed 属性 if (todo) { todo.completed = !todo.completed; } }, }, }); // --- 导出 Actions 和 Reducer --- // 导出生成的 Action Creators,用于在组件中 dispatch export const { addTodo, removeTodo, toggleCompleted } = todoListSlice.actions; // 导出 reducer,用于注入到 Redux Store 中 export default todoListSlice.reducer;

app.tsx

import { useState } from 'react' import './App.css' import Count from './pages/Count' import TodoList from './pages/TodoList' function App(){ return ( <> <h1>Redux Demo</h1> <Count /> <TodoList /> </> ) } export default App
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/25 5:37:58

Windows家庭版远程桌面终极解决方案:RDP Wrapper完全指南

Windows家庭版远程桌面终极解决方案&#xff1a;RDP Wrapper完全指南 【免费下载链接】rdpwrap RDP Wrapper Library 项目地址: https://gitcode.com/gh_mirrors/rd/rdpwrap 想要在Windows家庭版上实现专业级远程桌面功能&#xff1f;&#x1f60a; RDP Wrapper Library…

作者头像 李华
网站建设 2025/12/22 14:46:44

2小时,我搭了一套大客户销售漏斗系统,瓶颈、流失、增长一眼识别

上周一个朋友找我&#xff0c;说他们大客户团队最近状态很奇怪&#xff1a;机会不少&#xff0c;拜访也很勤&#xff0c;但签约进度总是拖&#xff0c;一到复盘就不知道问题在哪。这类情况太常见了。不是团队不努力&#xff0c;而是大家缺少一个能真实反映销售推进情况的漏斗系…

作者头像 李华
网站建设 2026/1/26 1:00:53

基于FLUX.1-dev的开源项目推荐:这些技术博客值得关注

基于FLUX.1-dev的开源项目推荐&#xff1a;这些技术博客值得关注 在生成式AI迅猛发展的今天&#xff0c;文本到图像模型早已不再是“画个大概”的玩具工具&#xff0c;而是逐步成为创意设计、内容生产乃至工业可视化中的核心引擎。从Stable Diffusion掀起平民化创作浪潮&#x…

作者头像 李华
网站建设 2026/1/26 3:07:13

LLM基础知识,langchainV1.0讲解(一)

NLP是什么&#xff1f;NLP&#xff1a;自然语言处理它的作用就是让计算机“理解、处理和生成人类语言”。NLP发展史1. 基于规则这个阶段的NLP主要用于把自然语言中的信息&#xff0c;提取成程序能直接用的字段。比如抽取时间、日期抽取金额、数量抽取编号、手机号、身份证号用户…

作者头像 李华
网站建设 2026/1/24 14:43:09

git 下载 Qwen3-32B模型时遇到的问题及解决方案

下载 Qwen3-32B 模型时的实战避坑指南 在当前大模型落地加速的背景下&#xff0c;越来越多团队开始尝试将高性能开源模型集成到实际业务中。通义千问最新发布的 Qwen3-32B&#xff0c;作为一款拥有320亿参数、支持128K超长上下文的语言模型&#xff0c;在代码生成、复杂推理和多…

作者头像 李华