0


【实战】用 Custom Hook + TS泛型实现 useArray

文章目录


一、题目

完善自定义 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
版权归原作者 程序边界 所有, 如有侵权,请联系我们删除。

“【实战】用 Custom Hook + TS泛型实现 useArray”的评论:

还没有评论