【React入门实战】实现Todo代办

2023-11-10 03:39

本文主要是介绍【React入门实战】实现Todo代办,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 效果
    • 功能-状态管理
      • 相关接口定义
      • 相关方法定义
    • UI
      • input输入框:回车添加todo
      • 标题
      • 列表
      • 列表项
      • Main
    • 总体代码

非常简单入门的react-todo练习,代码写的很小白。

效果

技术栈:react-typeScript

  • 数据分为代办Todo已办完Done,可以点击复选框切换状态
  • 可以添加代办事件
  • 会用到useStateuseReducer,详情看状态管理 – React 中文文档

在这里插入图片描述
接下来是代码实现。

功能-状态管理

相关参考:
TypeScript中的标记联合类型:实现Todo代办-CSDN博客
迁移状态逻辑至 Reducer 中 – React 中文文档 (docschina.org)

相关接口定义

Todo的状态表示:

text表示代办内容,done表示是否完成,id表示它在列表中的位置。

interface Todo {readonly text: string;readonly done: boolean;readonly id: number;
}

对Todo的操作表示:

interface AddTodo {type: "Add_TODO";text: string;
}interface ToggleTodo {type: "TOGGLE_TODO";index: number;
}// 操作只有添加todo和修改todo两种
type TodoAction = AddTodo | ToggleTodo;

相关方法定义

操作Todo的方法:

// 点击修改状态
function todoReducer(list: Array<Todo>, action: TodoAction): Array<Todo> {switch (action.type) {case "Add_TODO": {return [...list,{text: action.text,done: false,id: list.length,},];}case "TOGGLE_TODO": {return list.map((item, index) => {if (index !== action.index) {return item;}return {text: item.text,done: !item.done,id: item.id,};});}default: {return list;}}
}

useReducer部分:写在比较父级的组件中。把对应方法用prop的方式传给需要用的子组件。此博客写在了Main组件中。

// useReducer
const [todoList, dispatch] = useReducer(todoReducer, initTodo);function handleAddTodo(text: string) {dispatch({type: "Add_TODO",text: text,});
}function handleToggleTodo(index: number) {dispatch({type: "TOGGLE_TODO",index: index,});
}

模拟的数据:initTodo

// 模拟数据
const initTodo: Array<Todo> = [{text: "吃饭",done: true,id: 0,},{text: "睡觉",done: true,id: 1,},{text: "上班",done: true,id: 2,},{text: "下班",done: false,id: 3,},{text: "运动",done: false,id: 4,},{text: "听歌",done: false,id: 5,},
];

UI

react是非常组件化的框架。此Todo可以拆成好几个组件:

  • input输入框:回车添加todo
  • 标题
  • 列表:分开显示Todo/Done的列表
  • 列表项

input输入框:回车添加todo

这里需要用useState管理input输入的状态。

注意:每个input框都要绑定onChange或readonly,否则会报错。

当回车时,添加输入框中的值到Todo的列表,即触发前面定义的handleAddTodo方法。此方法在这里没有定义,因此要从定义它的地方(Main)传过来。

function Add({ handleAddTodo }: { handleAddTodo: Function }) {const [inputValue, setInputValue] = useState("");return (<><div className="header"><inputtype="text"value={inputValue}onChange={(e) => {setInputValue(e.target.value);}}onKeyDown={(e) => {if (e.key === "Enter") {handleAddTodo(inputValue);setInputValue("");}}}placeholder="在这里添加新的代办事件"/></div></>);
}

标题

// 标题
function ShowTitle({ title }: { title: string }) {return (<><h2>{title}</h2></>);
}

列表

  • todoList是reduce中管理的所有事项的列表。
  • done表示当前列表是代办(false)还是已完成(true)
  • handleToggleTodo是点击复选框更改列表项状态的方法
// 展示todo的列表
function ShowList({todoList,done,handleToggleTodo,
}: {todoList: Array<Todo>;done: boolean;handleToggleTodo: Function;
}) {const data = todoList.filter((item) => {return item.done === done;});const show = data.map((item) => {return (<ListItemkey={item.id}item={item}handleToggleTodo={handleToggleTodo}></ListItem>);});return <>{show}</>;
}

列表项

// list的每一项
function ListItem({item,handleToggleTodo,
}: {item: Todo;handleToggleTodo: Function;
}) {return (<div className="item"><inputtype="checkbox"checked={item.done}onChange={() => {handleToggleTodo(item.id);}}name=""id=""/>{item.text}</div>);
}

Main

function Main() {// useReducerconst [todoList, dispatch] = useReducer(todoReducer, initTodo);function handleAddTodo(text: string) {dispatch({type: "Add_TODO",text: text,});}function handleToggleTodo(index: number) {dispatch({type: "TOGGLE_TODO",index: index,});}return (<><Add handleAddTodo={handleAddTodo}></Add><ShowTitle title={"Todo"}></ShowTitle><ShowListtodoList={todoList}done={false}handleToggleTodo={handleToggleTodo}></ShowList><ShowTitle title={"Done"}></ShowTitle><ShowListtodoList={todoList}done={true}handleToggleTodo={handleToggleTodo}></ShowList></>);
}

总体代码

import { useState, useReducer } from "react";// 标题
function ShowTitle({ title }: { title: string }) {return (<><h2>{title}</h2></>);
}// 添加todo的输入框
function Add({ handleAddTodo }: { handleAddTodo: Function }) {const [inputValue, setInputValue] = useState("");return (<><div className="header"><inputtype="text"value={inputValue}onChange={(e) => {setInputValue(e.target.value);}}onKeyDown={(e) => {if (e.key === "Enter") {handleAddTodo(inputValue);setInputValue("");}}}placeholder="在这里添加新的代办事件"/></div></>);
}// list的每一项
function ListItem({item,handleToggleTodo,
}: {item: Todo;handleToggleTodo: Function;
}) {return (<div className="item"><inputtype="checkbox"checked={item.done}onChange={() => {handleToggleTodo(item.id);}}name=""id=""/>{item.text}</div>);
}// 展示todo的列表
function ShowList({todoList,done,handleToggleTodo,
}: {todoList: Array<Todo>;done: boolean;handleToggleTodo: Function;
}) {const data = todoList.filter((item) => {return item.done === done;});const show = data.map((item) => {return (<ListItemkey={item.id}item={item}handleToggleTodo={handleToggleTodo}></ListItem>);});return <>{show}</>;
}function Main() {// useReducerconst [todoList, dispatch] = useReducer(todoReducer, initTodo);function handleAddTodo(text: string) {dispatch({type: "Add_TODO",text: text,});}function handleToggleTodo(index: number) {dispatch({type: "TOGGLE_TODO",index: index,});}return (<><Add handleAddTodo={handleAddTodo}></Add><ShowTitle title={"Todo"}></ShowTitle><ShowListtodoList={todoList}done={false}handleToggleTodo={handleToggleTodo}></ShowList><ShowTitle title={"Done"}></ShowTitle><ShowListtodoList={todoList}done={true}handleToggleTodo={handleToggleTodo}></ShowList></>);
}function App() {return (<><div className="main"><Main></Main></div></>);
}interface Todo {readonly text: string;readonly done: boolean;readonly id: number;
}interface AddTodo {type: "Add_TODO";text: string;
}interface ToggleTodo {type: "TOGGLE_TODO";index: number;
}// 操作只有添加todo和修改todo两种
type TodoAction = AddTodo | ToggleTodo;// 点击修改状态
function todoReducer(list: Array<Todo>, action: TodoAction): Array<Todo> {switch (action.type) {case "Add_TODO": {return [...list,{text: action.text,done: false,id: list.length,},];}case "TOGGLE_TODO": {return list.map((item, index) => {if (index !== action.index) {return item;}return {text: item.text,done: !item.done,id: item.id,};});}default: {return list;}}
}// 模拟数据
const initTodo: Array<Todo> = [{text: "吃饭",done: true,id: 0,},{text: "睡觉",done: true,id: 1,},{text: "上班",done: true,id: 2,},{text: "下班",done: false,id: 3,},{text: "运动",done: false,id: 4,},{text: "听歌",done: false,id: 5,},
];export default App;

这篇关于【React入门实战】实现Todo代办的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/380187

相关文章

Spring StateMachine实现状态机使用示例详解

《SpringStateMachine实现状态机使用示例详解》本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解... 目录什么是状态机使用示例什么是状态机状态机是计算机科学中的​​核心建模工具​​,用于描述对象在其生命

Spring Boot 结合 WxJava 实现文章上传微信公众号草稿箱与群发

《SpringBoot结合WxJava实现文章上传微信公众号草稿箱与群发》本文将详细介绍如何使用SpringBoot框架结合WxJava开发工具包,实现文章上传到微信公众号草稿箱以及群发功能,... 目录一、项目环境准备1.1 开发环境1.2 微信公众号准备二、Spring Boot 项目搭建2.1 创建

IntelliJ IDEA2025创建SpringBoot项目的实现步骤

《IntelliJIDEA2025创建SpringBoot项目的实现步骤》本文主要介绍了IntelliJIDEA2025创建SpringBoot项目的实现步骤,文中通过示例代码介绍的非常详细,对大家... 目录一、创建 Spring Boot 项目1. 新建项目2. 基础配置3. 选择依赖4. 生成项目5.

MySQL 多列 IN 查询之语法、性能与实战技巧(最新整理)

《MySQL多列IN查询之语法、性能与实战技巧(最新整理)》本文详解MySQL多列IN查询,对比传统OR写法,强调其简洁高效,适合批量匹配复合键,通过联合索引、分批次优化提升性能,兼容多种数据库... 目录一、基础语法:多列 IN 的两种写法1. 直接值列表2. 子查询二、对比传统 OR 的写法三、性能分析

Linux下删除乱码文件和目录的实现方式

《Linux下删除乱码文件和目录的实现方式》:本文主要介绍Linux下删除乱码文件和目录的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下删除乱码文件和目录方法1方法2总结Linux下删除乱码文件和目录方法1使用ls -i命令找到文件或目录

SpringBoot+EasyExcel实现自定义复杂样式导入导出

《SpringBoot+EasyExcel实现自定义复杂样式导入导出》这篇文章主要为大家详细介绍了SpringBoot如何结果EasyExcel实现自定义复杂样式导入导出功能,文中的示例代码讲解详细,... 目录安装处理自定义导出复杂场景1、列不固定,动态列2、动态下拉3、自定义锁定行/列,添加密码4、合并

mybatis执行insert返回id实现详解

《mybatis执行insert返回id实现详解》MyBatis插入操作默认返回受影响行数,需通过useGeneratedKeys+keyProperty或selectKey获取主键ID,确保主键为自... 目录 两种方式获取自增 ID:1. ​​useGeneratedKeys+keyProperty(推

Spring Boot集成Druid实现数据源管理与监控的详细步骤

《SpringBoot集成Druid实现数据源管理与监控的详细步骤》本文介绍如何在SpringBoot项目中集成Druid数据库连接池,包括环境搭建、Maven依赖配置、SpringBoot配置文件... 目录1. 引言1.1 环境准备1.2 Druid介绍2. 配置Druid连接池3. 查看Druid监控

Linux在线解压jar包的实现方式

《Linux在线解压jar包的实现方式》:本文主要介绍Linux在线解压jar包的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux在线解压jar包解压 jar包的步骤总结Linux在线解压jar包在 Centos 中解压 jar 包可以使用 u

Python办公自动化实战之打造智能邮件发送工具

《Python办公自动化实战之打造智能邮件发送工具》在数字化办公场景中,邮件自动化是提升工作效率的关键技能,本文将演示如何使用Python的smtplib和email库构建一个支持图文混排,多附件,多... 目录前言一、基础配置:搭建邮件发送框架1.1 邮箱服务准备1.2 核心库导入1.3 基础发送函数二、