【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;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/188409.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php实现钉钉机器人推送消息和图片内容(完整版)

先来看下实现效果: 代码如下: function send_dingtalk_markdown($webhook , $title , $message "", $atMobiles [], $atUserIds []) {$data ["msgtype" > "markdown","markdown" > ["title" > $title,&quo…

一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?

目录 1解题思路&#xff1a; 2代码如下&#xff1a; 3运行结果&#xff1a; 4总结&#xff1a; 5介绍&#xff1a; 1解题思路&#xff1a; 利用循环&#xff08;穷举法&#xff09;来 对 所 需要的数 进行确定 2代码如下&#xff1a; #include <stdio.h>int main() …

Java自学第9课:JSP基础及内置对象

目录&#xff1a; 目录 1 JSP基础知识架构 1 指令标识 1 Page命令 2 Including指令 3 taglib指令 2 脚本标识 1 JSP表达式 2 声明标识 3 代码片段 3 JSP注释 1 HTML注释 2 带有JSP表达式的注释 3 隐藏注释 4 动态注释 4 动作标识 1 包含文件标识 2 请求转发标…

原文远知行COO张力加盟逐际动力 自动驾驶进入视觉时代?

11月7日&#xff0c;通用足式机器人公司逐际动力LimX Dynamics官宣了两位核心成员的加入。原文远知行COO张力出任逐际动力联合创始人兼COO&#xff0c;香港大学长聘副教授潘佳博士为逐际动力首席科学家。 根据介绍&#xff0c;两位核心成员的加入&#xff0c;证明一家以技术驱…

Stable Diffusion webui 源码调试(三)

Stable Diffusion webui 源码调试&#xff08;三&#xff09; 个人模型主页&#xff1a;LibLibai stable-diffusion-webui 版本&#xff1a;v1.4.1 内容更新随机&#xff0c;看心情调试代码~ shared 变量 shared变量&#xff0c;简直是一锅大杂烩&#xff0c;shared变量存放…

第三届 “鹏城杯”(初赛)

第三届 “鹏城杯”&#xff08;初赛&#xff09; WEB Web-web1 反序列化tostring打Hack类 Payload:O%3A1%3A%22H%22%3A1%3A%7Bs%3A8%3A%22username%22%3BO%3A6%3A%22Hacker%22%3A2%3A%7Bs%3A11%3A%22%00Hacker%00exp%22%3BN%3Bs%3A11%3A%22%00Hacker%00cmd%22%3BN%3B%7D%7D…

Leetcode Hot100之六:42.接雨水

题目 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 提示&#xff1a; n height.length 1 < n < 2 * 10^4 0 < height[i] < 10^5 思路 暴力循环&#xff1a; 原本的思路是左边界i从左到…

原型制作神器ProtoPie的使用Unity与网页跨端交互

什么是ProtoPie&#xff1f; ProtoPie是一款面向设计师的软件原型设计工具&#xff0c;例如制作App界面交互展示&#xff0c;制作好的原型可以一键发布到Web服务器&#xff0c;就可以浏览器访问。由于其内置了大量常用交互类型&#xff0c;以及"程序化"模块&#xf…

人工智能基础_机器学习024_梯度下降进阶_L1正则可视化图形---人工智能工作笔记0064

然后我们就来用代码实现一下L1正则的可视化,我们来看看 首先导入 import numpy as np 数学计算 import matplotlib.pyplot as plt 画图用的 然后我们把L1正则的公式写出来 可以看到L1的正则 其实就是w1和w2的绝对值相加对吧 然后这里我们写一个公式: f(x,y) = |x|+|y| …

可以体现Python语法精妙的十个例子!

文章目录 前言1.for - else2.一颗星*和两颗星**3.三元表达式4.with - as5.列表推导式6.列表索引的各种骚操作7.lambda函数8.yield 以及生成器和迭代器9.装饰器10.巧用断言assertPython技术资源分享1、Python所有方向的学习路线2、学习软件3、精品书籍4、入门学习视频5、实战案例…

《网络协议》02. 物理层 · 数据链路层 · 网络层

title: 《网络协议》02. 物理层 数据链路层 网络层 date: 2022-08-31 22:26:48 updated: 2023-11-08 06:58:52 categories: 学习记录&#xff1a;网络协议 excerpt: 物理层&#xff08;数据通信模型&#xff0c;信道&#xff09;、数据链路层&#xff08;封装成帧&#xff0c…

演示文稿制作软件 Deckset mac中文版介绍

Deckset mac是一款Mac上的演示文稿制作软件&#xff0c;它可以让你使用Markdown语言快速地创建演示文稿。与传统的演示文稿制作软件相比&#xff0c;Deckset采用了全新的设计理念&#xff0c;旨在让用户更加专注于内容的创作&#xff0c;而不是花费过多的时间在排版和设计上。 …

Kotlin文件和类为什么不是一对一关系

在Java中&#xff0c;一个类文件的public类名必须和文件名一致&#xff0c;如何不一致就会报异常&#xff0c;但是在kotlin的文件可以和类名一致&#xff0c;也可以不一致。这种特性&#xff0c;就跟c有点像&#xff0c;毕竟c的.h 和 .cpp文件是分开的。只要最终编译的时候对的…

2000-2022年上市公司数字化转型同群效应数据

2000-2022年上市公司数字化转型同群效应数据 1、时间&#xff1a;2000-2022年 2、指标&#xff1a;股票代码、年份、行业代码、行政区划代码、数字化转型程度-A、数字化转型程度-B、同行业同群-数字化转型程度-A_均值、同行业同群-数字化转型程度-A_中位数、同省份同群-数字化…

【Redis】Redis与SSM整合Redis注解式缓存Redis解决缓存问题

一&#xff0c;Redis与ssm整合 1.1 pom.xml配置 在pom.xml中配置相关的redis文件 redis文件&#xff1a; <redis.version>2.9.0</redis.version> <redis.spring.version>1.7.1.RELEASE</redis.spring.version><dependency><groupId>red…

JavaWeb Day09 Mybatis-基础操作01-增删改查

目录 环境准备 ①Emp.sql ②Emp.java 一、删除 ①Mapper层 ②测试类 ③预编译SQL&#xff08;查看mybatis日志&#xff09; 1.性能 2.安全 ④总结 二、新增 ①Mapper层 ②测试类 ③结果 ④新增&#xff08;主键返回&#xff09; 1.Mapper层 2.测试类 ⑤总结​…

Fortran 中的指针

Fortran 中的指针 指针可以看作一种数据类型 指针存储与之关联的数据的内存地址变量指针&#xff1a;指向变量数组指针&#xff1a;指向数组过程指针&#xff1a;指向函数或子程序指针状态 未定义未关联 integer, pointer::p1>null() !或者 nullify(p1) 已关联 指针操作 指…

【C++】函数指针 ① ( 函数三要素 | 函数类型 | 函数指针类型 | 函数类型重命名 )

文章目录 一、函数类型 和 函数指针类型1、函数三要素2、函数类型3、函数指针类型4、函数类型重命名 二、代码示例 - 函数类型重命名1、代码分析2、完整代码示例 一、函数类型 和 函数指针类型 1、函数三要素 函数原型有三个重要要素 : 函数名称 : 使用 标识符 为函数命名 ; 用…

K8S容器内安装cur/telnet命令(Alpine Linux离线环境安装curl/telnet或其他工具)

背景 需求&#xff1a; 微服务的基础是镜像&#xff0c;通常在最小化的Linux镜像中安装jdk&#xff0c;然后运行编译好的java程序。将镜像运行到K8S上就得到了微服务Pod&#xff0c;Pod通常使用安装K8S时配置的私有网段&#xff0c;与宿主机不同。很多时候需要排查从Pod网段内…

人工智能基础_机器学习022_使用正则化_曼哈顿距离_欧氏距离_提高模型鲁棒性_过拟合_欠拟合_正则化提高模型泛化能力---人工智能工作笔记0062

然后我们再来看一下,过拟合和欠拟合,现在,实际上欠拟合,出现的情况已经不多了,欠拟合是 在训练集和测试集的准确率不高,学习不到位的情况. 然后现在一般碰到的是过拟合,可以看到第二个就是,完全就把红点蓝点分开了,这种情况是不好的, 因为分开是对训练数据进行分开的,如果来…