React 自定义 Hooks

引入

我们之前会使用 useState, useMemo 或者各种各样的, 使用 use 开头的函数, 这些函数就叫做 React 的 Hooks.

当我们想要在两个函数之间共享逻辑的时候, 我们会把它提取到第三个函数中. 这个第三个函数就是我们的 Hooks 了.

另外, Hook 必须用 use 开头, 否则的话 React 无法检查 Hook 是否违反了 Hook 的规则.

自定义 Hooks

需要注意, Hooks 做的是将逻辑进行抽离, 不涉及 UI 部分. 例如下面这段代码, 模拟的进行了一个数据的请求.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import { useEffect, useState } from "react";

interface IUser {
name: string;
age: number;
}

function App() {
const [user, setUser] = useState<IUser>();

// 假设 现在有一个请求数据的操作
const fetchData = async () => {
new Promise((resolve) => {
setTimeout(() => {
resolve({ name: "yyt", age: 18 });
}, 1000);
}).then((res: IUser) => {
const tmpUser: IUser = {
name: res.name,
age: res.age,
};
setUser(tmpUser);
});
};

useEffect(() => {
fetchData();
}, []);

return (
<>
<h1>User Info</h1>
<h2>{user?.name}</h2>
<h2>{user?.age}</h2>
</>
);
}

export default App;

可能这个请求的操作我们会多次用到, 那么就可以直接封装为一个 hook 了.


这里直接创建一个 hook, 叫做 useUserInfo.

随后, 就可以把所有的逻辑放在里面了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// useUserInfo.tsx
import { useEffect, useState } from "react";

interface IUser {
name: string;
age: number;
}

// 注意, 只要是use开头的函数, 就是自定义钩子, 这个时候就可以直接使用React的钩子了
const useUserInfo = () => {
const [user, setUser] = useState<IUser>({
name: "默认用户名",
age: 0,
});

const fetchData = async () => {
new Promise((resolve) => {
setTimeout(() => {
resolve({ name: "yyt", age: 18 });
}, 1000);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
}).then((res: IUser) => {
const tmpUser: IUser = {
name: res.name,
age: res.age,
};
setUser(tmpUser);
});
};

useEffect(() => {
fetchData();
}, []);

// 注意 函数的最后, 就是返回我们想要的东西就行
return user;
};

export default useUserInfo;

现在, 回到页面中, 就可以直接使用这个自定义钩子来实现目标效果了.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import useUserInfo from "./hooks/useUserInfo";

function App() {
// 这里直接获取数据就行 甚至不需要使用useState
const user = useUserInfo();

return (
<>
<h1>User Info</h1>
<h2>{user?.name}</h2>
<h2>{user?.age}</h2>
</>
);
}

export default App;

现在页面显示仍然正常, 并且保留了响应式. 这就是自定义 Hooks 了.

总结

自定义 Hooks, 其实就是一种特殊的写法, 允许将 React 的 hooks 函数抽象出来单独使用的一种方法. 本质上就是将一些代码抽象为函数, 不过这些代码中用到了 React 的钩子函数.

为了处理这种特殊的函数, 我们需要将这些函数写成一个 Hook, 方便后期的调用.