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

news/2024/7/15 19:34:20 标签: javascript, 前端, react.js

文章目录

  • 一、题目
  • 二、答案(非标准)
  • 三、关键知识点
    • 1.Custom Hook
      • 关键点
      • 案例
        • useMount
        • useDebounce
    • 2.TS 泛型
      • 关键点


一、题目

完善自定义 Hook —— useArray ,使其能够完成 tryUseArray 组件中测试的功能:

  • 入参:数组
  • 返回值:
    • value:最新状态的数组;
    • add:添加元素;
    • removeIndex:移除数组特定位置的元素;
    • clear:清空数组;

相关文件代码:

  • src\utils\index.ts
javascript">import { useEffect, useState } from "react";

export const useMount = (cbk: () => void) => useEffect(() => cbk(), []);

export const useArray = () => {};
  • src\tryUseArray.tsx
javascript">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
javascript">import "./App.css";
import TryUseArray from "tryUseArray";

function App() {
  return (
    <div className="App">
      <TryUseArray />
    </div>
  );
}

export default App;

答 答
案 案
在 在
后 后
面 面
, ,
没 没
有 有
完 完
成 成
不 不
要 要
偷 偷
看 看
哦 哦
! !

二、答案(非标准)

javascript">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

  • 封装
javascript">/**
 * @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;
};
  • 调用
javascript">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 泛型

http://www.niftyadmin.cn/n/131268.html

相关文章

超赞,用python实现流媒体服务器功能,寥寥几句搞定。

步骤&#xff1a; 要使用Python将实时摄像机传送流写入H5页面&#xff0c;可以使用以下步骤。 1、安装必要的软件包。您需要安装OpenCV和Flask以及gunicorn 与 gevent 。您可以通过在终端中运行以下命令来执行此操作。 pip install opencv-python pip install Flask pip ins…

Altium Designer(AD)软件使用记录00-绪论

目录Altium Designer(AD)软件使用记录00-绪论Altium Designer(AD)软件使用记录00-绪论 掐指一算&#xff0c;从接触AD这个软件到现在都已经有7年之久了&#xff0c;中间断断续续的使用着。看着现在AD软件一年更新好多次&#xff0c;一个手掌都数不过来了。AD这个软件更新速度实…

Linux设备的I/O模型

背景&#xff1a;进程休眠和唤醒为了把一个进程设置为睡眠状态&#xff0c;需要把这个进程从TASK_RUNNING(可运行状态或就绪态)状态设置为TASK_INTERRUPTIBLE(浅度睡眠)或TASK_NUINTERRUPTIBLE(深度睡眠)状态&#xff0c;并且从进程调度器的运行队列中移走&#xff0c;我们称这…

linux安装influxdb-rpmyum方式

一、influxdb的安装InfluxDB简介时序数据库InfluxDB版是一款专门处理高写入和查询负载的时序数据库&#xff0c;用于存储大规模的时序数据并进行实时分析&#xff0c;包括来自DevOps监控、应用指标和IoT传感器上的数据主要特点&#xff1a;专为时间序列数据量身订造高性能数据存…

2023 HBU 天梯赛第一次测试 题目集

目录 1 建校日期 2 发射小球 3 背上书包去旅行 4 吉利的数字 5 向前走 6 热水器 7 走方格 8 朋友圈 9 交保护费 10 走方格 11 和与积 12 缩短字符串 13 买木棒 1 建校日期 在2022 ICPC沈阳站上&#xff0c;东北大学命题组给参赛的选手们出了一道签到题&#xff0…

秒懂算法 | DP概述和常见DP面试题

动态(DP)是一种算法技术,它将大问题分解为更简单的子问题,对整体问题的最优解决方案取决于子问题的最优解决方案。本篇内容介绍了DP的概念和基本操作;DP的设计、方程推导、记忆化编码、递推编码、滚动数组以及常见的DP面试题。 01、DP概述 1. DP问题的特征 下面以斐波那…

JavaEE课程实践-Servlet的部署(tomcat服务器)

目录 Servlet简述 tomcat服务器的安装和运行 Servlet的部署 部署具体步骤 一、创建maven工程 二、创建Servlet类 三、导入相应jar包 四、编写Servlet代码 五、运行maven项目&#xff0c;启动tomcat服务器 六、测试访问是否成功。 Servlet简述 Servlet 是 Java EE 技术…

【项目实战】基于SpringCloud Gateway的webflux与Google的kaptcha实现图形验证码功能

一、背景 基于SpringCloud 微服务架构的项目中,需要使用图形验证码,以下是使用的记录。 二、验证码功能介绍 有两种工具生成验证码:Captcha 和 kaptcha 2.1 Captcha 介绍 2.1.1 Captcha 是什么? 用Java编写的简单但功能强大的验证代码库,具有零依赖性。 google cap…