背景
在前后分离的业务场景下,如今客户端与服务端的桥梁是那一个个API。
今天, 我们聊聊在typescript
和 react hooks
的技术栈下,如何更好的管理api。
先分析一下在使用API时,我们需要有哪一些能力:
- 声明api时,要简单一些,别太多样板代码,因为我们懒。
- 调用api时,得告诉我们需要的入参和出参,并且要知道它是哪个模块的,没人会记得以前写的代码。
- 调用api时,最好简单一些,得告诉我们返回啥了,而且别天天需要调用
then、setState、setloading
的存数据,浪费时间,也不想多写,因为比较懒。 - 等等,还有好多想满足的,今天先聊这三个,因为我懒。
现在上面的三点,typescript
和react hooks
能帮我们做什么。
聪明的你肯定想到了,第一点
和第二点
,typescript
的类型推导可以帮我们,而第三点
我们封装一个自定义的hook
,好像也可以,下面我们用简单的代码来搞搞看。
API生成函数
下面这个API生成的函数,可以帮忙我们生成函数了,看这代码好像是可以调用createGetApi
然后生成一个基于axios
配置的函数。
import { AxiosRequestConfig, Method } from 'axios'
type ApiConfig<Params = any, Data = any> = AxiosRequestConfig & {
url: string
method?: Method
params?: Params
data?: Params
_response?: Data
[x: string]: any
}
type Service<Params = any, Data = any> = (headParams: Params, otherSet?: object) => ApiConfig<Params, Data>
const createGetApi = <Params = any, Data = any>(
apiConfig: ApiConfig
): Service<Params, Data> => (headParams: Params, otherSet = {}) => {
return {
...apiConfig,
params: headParams,
...otherSet
}
}
// 用用看
const getUser = createGetApi<
{ id: number },
{userName: string, password: string}
>({
url: 'http',
method: 'get'
})
复制代码
鼠标放上去,提示是这样子的,看来这个createGetApi
生成的api
已经知道自己要什么了。
我们搞定了第一点
想要,和第二点
的一半想要,第二点
的模块没有告诉我们,继续丰富下。
const nameSpace = {
user: {
getUser
},
analysis: {
getUser
},
}
export const useApi = () => {
return nameSpace
}
const TEST = () => {
const apis = useApi()
return (
<div>22</div>
)
}
复制代码
我们用ts的自动推导功能,让它告诉我们用哪些模块,模块有什么api。
现在,我们算是完成了第一点
和第二点
了,接下来看看第三点
咋弄。
请求器
上面说过,第三点
封装一个自定义的hook
就好了呀,然后hook
接收我们生成的api作为参数,这样写一次,以后用这个hook
就不用写很多代码了。
const useFetch = <Params, Data>(apiConfig: ApiConfig<Params, Data>) => {
const [loading, setLoading] = React.useState(false)
const [data, setData] = React.useState<Data>()
React.useEffect(() => {
setLoading(true)
axios(apiConfig)
.then((response) => {
setData(response.data as Data)
})
.finally(() => {
setLoading(false)
})
}, [])
return {
loading,
data
}
}
复制代码
我们根据第三点
写了一个简单的请求器,我们把一些懒得写的都封装进去了,不过error
捕捉懒得写,然后我们用一用,看看怎么样。
const TEST = () => {
const apis = useApi()
const { loading, data } = useFetch(apis.user.getUser({ id: 22 }))
if (!data) {
return 'loading'
}
return (
<div>{data.userName}</div>
)
}
复制代码
鼠标放上去看看, useFetch
能认识我们的api
啦,还把api
的出参也跟我们说。
把api
的参数改成string
看看,也提示入参错了。
好像,第三点
也实现了,api
和hook
认识了。
总结
这里我们总结下,上面的示例了一个简单高效的api管理方案。
typescript
的推导在coding过程中,能帮助避免一些错误,提高一些效率。
而react hook
带来的更多可能性,useFetch
的缩影则是个个开源库,如:
SWR等。
上面的方案,博主有一个更完善的方案在github上, 结合了丰富的业务功能,有兴趣可以关注下(最好帮忙来个star):github.com/fridaymarke…