前言
在前端开发过程中,需要经常会处理一些异步逻辑(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
会立刻检查出类型错误。