文章目录
一、题目
完善自定义 Hook —— useArray ,使其能够完成 tryUseArray 组件中测试的功能:
- 入参:数组
- 返回值: - value:最新状态的数组;- add:添加元素;- removeIndex:移除数组特定位置的元素;- clear:清空数组;
相关文件代码:
- src\utils\index.ts
import{ useEffect, useState }from"react";exportconstuseMount=(cbk:()=>void)=>useEffect(()=>cbk(),[]);exportconstuseArray=()=>{};
- src\tryUseArray.tsx
import{ useArray, useMount }from"utils";constTryUseArray=()=>{constpersons:{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>);};exportdefault TryUseArray;
- src\App.tsx
import"./App.css";import TryUseArray from"tryUseArray";functionApp(){return(<div className="App"><TryUseArray /></div>);}exportdefault 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// }// }exportconst 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
- 封装
exportconstuseMount=(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 延迟的是存储在队列中的上一次变化)
*/exportconst 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 泛型
本文转载自: https://blog.csdn.net/qq_32682301/article/details/129382797
版权归原作者 程序边界 所有, 如有侵权,请联系我们删除。
版权归原作者 程序边界 所有, 如有侵权,请联系我们删除。