前言
在前端开发过程中,需要经常会处理一些异步逻辑(Promise、fetch/axios 等等),并且需要监听这个过程。
通常我们是这样做的,在请求开始时设置 loading 为 true,结束时设置为 false,如下:
import { useState } from 'react';
const query = (id: number) => new Promise<string>(resolve => setTimeout(() => resolve(id + 'success'), 2000));
function Demo() {
const [loading, setLoading] = useState<boolean>(false);
const [data, setData] = useState<string>('数据为空');
const queryData = async () => {
setLoading(true);
const res = await query(1);
setData(res);
setLoading(false);
}
return <div>
{loading ? '请求中' : data}
<div>
<button onClick={() => { queryData() }}>发起请求</button>
</div>
</div>
}
export { Demo }
但是这样做非常的不优雅,如果存在多个异步逻辑,就会使得导致代码变得难以阅读和混乱。
所以在 microhook 中提供了一个解决方案, 使用其中的 useLoading 自定义 hook 可以有效解决这个问题。
安装
通过 npm 或者 yarn 安装,并添加到 dependencies 中:
npm i microhook
使用
首先从安装好的 microhook 中引入 useLoading:
import { useLoading } from 'microhook';
然后将异步逻辑传入到 useLoading 中,hook 会返回一个 response 结果和一个 action 集合。
response 包含如下内容:
loading请求的状态data请求返回的结果
action 包含的是 hook 提供的动作,这边包含如下:
wrapRequest通过这个方法来调用传入的异步逻辑,并且接受的参数都会透传到原始的方法中,从而监听pending的状态
所以将刚才的 case 改造下实现同样的功能,如下:
import { useLoading } from 'microhook';
const query = (id: number) => new Promise<string>(resolve => setTimeout(() => resolve(id + 'success'), 2000));
function Demo() {
const [response, action] = useLoading(query);
return <div>
{response.loading ? '请求中' : response.data}
<div>
<button onClick={() => { action.wrapRequset(1) }}>发起请求</button>
</div>
</div>
}
export { Demo }
通过这个hook,代码立刻就变得非常优雅了。
结合 typescript
useLoading 还支持 ts 类型的传入,可以指定 response.data 的类型和 wrapRequset 的入参类型, 只要在 hook 后面传入原始函数的类型即可,如 useLoading<typeof query>。
下面举个例子:
import { useLoading } from 'microhook';
const query = (id: number) => new Promise<string>(resolve => setTimeout(() => resolve(id + 'success'), 2000));
function Demo() {
const [response, action] = useLoading<typeof query>(query);
return <div>
{response.loading ? '请求中' : response.data}
<div>
<button onClick={() => { action.wrapRequset(1) }}>发起请求</button>
</div>
</div>
}
export { Demo }
在这个例子中 action.wrapRequset(1) 的参数只能是 number 类型, response.data 就被断言为 string,反之 ts 会立刻检查出类型错误。