一、标题
完满自定义 Hook —— useArray ,使其可以大概完成 tryUseArray 组件中测试的功能:
- 入参:数组
- 返回值:
- value:最新状态的数组;
- add:添加元素;
- removeIndex:移除数组特定位置的元素;
- clear:清空数组;
相干文件代码:
- import { useEffect, useState } from "react";
- export const useMount = (cbk: () => void) => useEffect(() => cbk(), []);
- export const useArray = () => {};
复制代码
- 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;
复制代码
- 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+ 中使用
案例
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]);
复制代码 留意区别于 节省
拓展学习:
2.TS 泛型
官方文档:
- TypeScript: Documentation - Generics
- 泛型(generic) - TypeScript 中文手册
关键点
- 不预先指定其具体的范例,而在使用的时间再进行定义
- 函数是对“值”的编程,泛型是对“范例”的编程
- 泛型是范例的变量
拓展学习:
来源:https://blog.csdn.net/qq_32682301/article/details/129382797
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |