文章目录

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

一、题目

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

相关文件代码:

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

关键点

  • 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 泛型

发表回复