【实战】用 Custom Hook + TS泛型实现 useArray
文章目录
- 一、题目
- 二、答案(非标准)
- 三、关键知识点
- 1.Custom Hook
- 关键点
- 案例
- useMount
- useDebounce
- 2.TS 泛型
- 关键点
一、题目
完善自定义 Hook —— useArray ,使其能够完成 tryUseArray 组件中测试的功能:
- 入参:数组
- 返回值:
- value:最新状态的数组;
- add:添加元素;
- removeIndex:移除数组特定位置的元素;
- clear:清空数组;
相关文件代码:
- src\utils\index.ts
import { useEffect, useState } from "react";export const useMount = (cbk: () => void) => useEffect(() => cbk(), []);export const useArray = () => {};
- src\tryUseArray.tsx
import { useArray, useMount } from "utils";const TryUseArray = () => {const persons: { name: string; age: number }[] = [{ name: "jack", age: 25 },{ name: "ma", age: 22 },];const { value, clear, removeIndex, add } = useArray(persons);useMount(() => {// 期待这里报错:Property 'notExist' does not exist on type '{ name: string; age: number; }[]'.// console.log(value.notExist);// 期待这里报错:Property 'age' is missing in type '{ name: string; }' but required in type '{ name: string; age: number; }'.// add({ name: "david" });// 期待这里报错:Argument of type 'string' is not assignable to parameter of type 'number'.// removeIndex("123");});return (<div>{/*期待: 点击以后增加 john */}<button onClick={() => add({ name: "john", age: 22 })}>add john</button>{/*期待: 点击以后删除第一项*/}<button onClick={() => removeIndex(0)}>remove 0</button>{/*期待:点击以后清空列表*/}<button style={{ marginBottom: "50px" }} onClick={() => clear()}>clear</button>{value.map((person, index) => (<div key={index} style={{ marginBottom: "30px" }}><span style={{ color: "red" }}>{index}</span><span>{person.name}</span><span>{person.age}</span></div>))}</div>);
};export default TryUseArray;
- src\App.tsx
import "./App.css";
import TryUseArray from "tryUseArray";function App() {return (<div className="App"><TryUseArray /></div>);
}export default App;
答答 答
案案 案
在在 在
后后 后
面面 面
,, ,
没没 没
有有 有
完完 完
成成 成
不不 不
要要 要
偷偷 偷
看看 看
哦哦 哦
!! !
二、答案(非标准)
import { useEffect, useState } from "react";// 我的练习作业
// export const useArray = <T>(array: T[]) => {
// const [value, setValue] = useState(array)
// const clear = () => setValue([])
// const removeIndex = (index: number) => setValue([...value].filter((item, _index) => _index !== index))
// const add = (item: item) => setValue([...value, item]))
// return {
// value, clear, removeIndex, add
// }
// }export const useArray = <T>(array: T[]) => {const [value, setValue] = useState(array);return {value,add: (item: T) => setValue([...value, item]),removeIndex: (index: number) => {const temp = [...value];temp.splice(index, 1);setValue(temp);},clear: () => setValue([]),};
};
三、关键知识点
1.Custom Hook
官方文档:自定义 Hook – React
关键点
- 定义 Custom Hook 是一个函数,名字必须以 use 开头
- hook 只能在 React 函数组件 或其他 Hook 函数中调用(普通
js/ts函数中不可用) - 相同的 Hook 不共享 state (重用状态逻辑的机制,所有 state 和副作用都是完全隔离的)
- 不要在循环,条件或嵌套函数中调用 Hook(建议在 Hook 内部使用循环,条件或嵌套函数)
- React 16.8+ 中使用
- Hook 规则 – React
案例
useMount
- 封装
export const useMount = (cbk: () => void) => useEffect(() => cbk(), []);
- 调用
import { useMount } from "utils";const [list, setList] = useState([]);useMount(() => {fetch(`${apiUrl}/list`).then(async (res) => {if (res.ok) {setList(await res.json());}});
});
useDebounce
- 封装
/*** @param { 值 } val* @param { 延时:默认 1000 } delay* @returns 在某段时间内多次变动后最终拿到的值(delay 延迟的是存储在队列中的上一次变化)*/
export const useDebounce = <V>(val: V, delay: number = 1000) => {const [tempVal, setTempVal] = useState(val);useEffect(() => {// 每次在 val 变化后,设置一个定时器const timeout = setTimeout(() => setTempVal(val), delay);// 每次在上一个 useEffect 处理完以后再运行(useEffect 的天然功能即是在运行结束的 return 函数中清除上一个(同一) useEffect)return () => clearTimeout(timeout);}, [val, delay]);return tempVal;
};
- 调用
import { useDebounce } from "utils";
// 对 param 进行防抖处理
const lastParam = useDebounce(param);
const [list, setList] = useState([]);useEffect(() => {fetch(// name=${param.name}&personId=${param.personId}`${apiUrl}/projects?${qs.stringify(lastParam)}`).then(async (res) => {if (res.ok) {setList(await res.json());}});
}, [lastParam]);
注意区别于 节流
拓展学习:
- 【笔记】Custom Hook
2.TS 泛型
官方文档:
- TypeScript: Documentation - Generics
- 泛型(generic) - TypeScript 中文手册
关键点
- 不预先指定其具体的类型,而在使用的时候再进行定义
- 函数是对“值”的编程,泛型是对“类型”的编程
- 泛型是类型的变量
拓展学习:
- 【笔记】TS 泛型
相关文章:
【实战】用 Custom Hook + TS泛型实现 useArray
文章目录一、题目二、答案(非标准)三、关键知识点1.Custom Hook关键点案例useMountuseDebounce2.TS 泛型关键点一、题目 完善自定义 Hook —— useArray ,使其能够完成 tryUseArray 组件中测试的功能: 入参:数组返回…...
【LeetCode】剑指 Offer(18)
目录 题目:剑指 Offer 35. 复杂链表的复制 - 力扣(Leetcode) 题目的接口: 解题思路: 代码: 过啦!!! 写在最后: 题目:剑指 Offer 35. 复杂链…...
Kubernetes节点运行时从Docker切换到Containerd
由于k8s将于1.24版本弃用dockershim,所以最近在升级前把本地的k8s切换到了Containerd运行时,目前我的k8s版本是1.22.5,一个master,二个Node的配置,以下做为一个操作记录日志整理,其它可以参考官网文档。 在…...
【编程基础之Python】12、Python中的语句
【编程基础之Python】12、Python中的语句Python中的语句赋值语句条件语句循环语句for循环while循环continue语句break语句continue与break的区别函数语句pass语句异常处理语句结论Python中的语句 Python是一种高级编程语言,具有简单易学的语法,适用于各…...
android h5餐饮管理系统myeclipse开发mysql数据库编程服务端java计算机程序设计
一、源码特点 android h5餐饮管理系统是一套完善的WEBandroid设计系统,对理解JSP java,安卓app编程开发语言有帮助(系统采用web服务端APP端 综合模式进行设计开发),系统具有完整的源代码和数据库,系统主要…...
容易混淆的嵌入式(Embedded)术语
因为做嵌入式开发工作虽然跳不出电子行业,但还是能接触到跨度较大的不同行当,身处不同的圈子。诸如医疗,银行,车载,工业;亦或者手机,PC,专用芯片;甚至可能横跨系统开发、…...
Nodejs 中 JSON 和 YAML 互相转换
JSON 转换成 YAML 1. 安装 js-yaml 库: npm install js-yaml2. 在程序中引入依赖库 const yaml require(js-yaml);3. 创建一个 js 对象, 代表 json 数据 const jsonData {name: John,age: 30,city: New York };4. 使用 yaml.dump() 把 js 对象转换成 YAML, 返回 YAML 字符…...
C++入门教程||C++ 修饰符类型||C++ 存储类
C 修饰符类型 C 允许在 char、int 和 double 数据类型前放置修饰符。修饰符用于改变基本类型的含义,所以它更能满足各种情境的需求。 下面列出了数据类型修饰符: signedunsignedlongshort 修饰符 signed、unsigned、long 和 short 可应用于整型&#…...
Android开发面试:Java知识答案精解
目录 Java 集合 集合概述 HashMap ConcurrentHashMap 泛型 反射 注解 IO流 异常、深浅拷贝与Java8新特性 Java异常 深浅拷贝 Java8新特性 并发 线程 线程池 锁 volatile JVM 内存区域 内存模型 类加载机制 垃圾回收机制 如何判断对象已死 Java 集合 …...
Windows上一款特别好用的画图软件
安装 废话不多说,打开windows的应用商店,搜索draw.io,点击获取即可。 画图 draw.io的布局左边是各种图形组件,中间是画布,右边是属性设置,文件扩展名是.drawio。 点击左边列表中的图形可以将它添加到画…...
html--学习
javascrapt交互,网页控制JavaScript:改变 HTML 图像本例会动态地改变 HTML <image> 的来源(src):点亮灯泡<script>function changeImage() {elementdocument.getElementById(myimage) #内存变量࿰…...
关于递归处理,应该怎么处理,思路是什么?
其实问题很简单,就是想要循环遍历整个data对象,来实现所有name转成label,但是想到里面还有children属性,整个children里面可能还会嵌套很多很多的name,如此循环,很难搞,知道使用递归,…...
重磅!牛客笔试客户端可防ChatGPT作弊
上线俩月,月活过亿。爆火的ChatGPT能代写文,撕代码,善玩梗,秒答题,几乎“无所不能”,争议也随之而来。调查显示,截至2023年1月,美国89%的大学生利用ChatGPT应付作业,53%的…...
春季训练营 | 前端+验证直通车-全实操项目实践,履历加成就业无忧
“芯动的offer”是2023年E课网联合企业全新推出集训培优班(线下),针对有一定基础(linux、verilog、uvm等)在校学生以及想要通过短时间的学习进入到IC行业中的转行人士,由资深IC设计工程师带教,通…...
2.详解URL
文章目录视图函数1.1endpoint简介1.2 装饰器注册路由源码浅析1.3 另一种注册路由的方式---app.add_url_rule()1.4 视图函数中添加自定义装饰器2 视图类2.1 视图类的基本写法3 详细讲解注册路由的参数3.1常用的参数3.2不常用的参数(了解)视图函数 1.1endpoint简介 endpint参数…...
Android特别的数据结构(二)ArrayMap源码解析
1. 数据结构 public final class ArrayMap<K,V> implements Map<K,V> 由两个数组组成,一个int[] mHashes用来存放Key的hash值,一个Object[] mArrays用来连续存放成对的Key和ValuemHashes数组按非严格升序排列初始默认容量为0减容ÿ…...
减少if else
1. 三目运算符 可以理解为条件 ?结果1 : 结果2 里面的?号是格式要求。也可以理解为条件是否成立,条件成立为结果1,否则为结果2。 实例: public String handle(int code) {if (code 1) {return "success";} else {return &quo…...
硕士毕业论文常见的排版小技巧
word排版陆续更新吧,更具我所遇到的一些小问题,总结上来 文章目录1.避免题注(图或者表的标题)与图或表格分不用页注意点:光标移动到表的题注后面2.设置论文的页眉关键点:需要将每一章节末尾,都要…...
JAVA开发(数据类型String和HasMap的实现原理)
在JAVA开发中,使用最多的数据类型恐怕是String 和 HasMap两种数据类型。在开发的过程中我们每天都使用的不亦乐乎。但是相信很多人都没有考虑过String数据类型的实现原理或者说是在数据结构中的存储原理,还有一个就是是HashMap,也很少有人去了…...
Hbase 映射到Hive
目录 一、环境配置修改 关闭掉hbase,zookeeper和hive服务 进入hive312/conf 修改hive-site.xml配置, 在代码最后添加配置 将hbase235的jar包全部拷贝到hive312的lib目录,并且所有的是否覆盖信息全部输入n,不覆盖 查看hive312下…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...
Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...
