【实战】用 Custom Hook + TS泛型实现 useArray
程序边界 2024-06-15 16:33:02 阅读 87
文章目录
一、题目二、答案(非标准)三、关键知识点1.Custom Hook关键点案例useMountuseDebounce 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 泛型
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。