在typescript和react hook下如何更好的管理API

吐槽君 分类:javascript

背景

在前后分离的业务场景下,如今客户端与服务端的桥梁是那一个个API。

今天, 我们聊聊在typescriptreact hooks的技术栈下,如何更好的管理api。

先分析一下在使用API时,我们需要有哪一些能力:

  1. 声明api时,要简单一些,别太多样板代码,因为我们懒。
  2. 调用api时,得告诉我们需要的入参和出参,并且要知道它是哪个模块的,没人会记得以前写的代码。
  3. 调用api时,最好简单一些,得告诉我们返回啥了,而且别天天需要调用then、setState、setloading的存数据,浪费时间,也不想多写,因为比较懒。
  4. 等等,还有好多想满足的,今天先聊这三个,因为我懒。

现在上面的三点,typescriptreact 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已经知道自己要什么了。

1618823474844.jpg

我们搞定了第一点想要,和第二点的一半想要,第二点的模块没有告诉我们,继续丰富下。

const nameSpace = {
    user: {
        getUser
    },
    analysis: {
        getUser
    },
}

export const useApi = () => {
    return nameSpace
}

const TEST = () => {
    const apis = useApi()
    return (
        <div>22</div>
    )
}

 

我们用ts的自动推导功能,让它告诉我们用哪些模块,模块有什么api。

image.png

现在,我们算是完成了第一点第二点了,接下来看看第三点咋弄。

请求器

上面说过,第三点封装一个自定义的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的出参也跟我们说。

image.png

api的参数改成string看看,也提示入参错了。

image.png

好像,第三点也实现了,apihook认识了。

总结

这里我们总结下,上面的示例了一个简单高效的api管理方案。

typescript的推导在coding过程中,能帮助避免一些错误,提高一些效率。

react hook带来的更多可能性,useFetch的缩影则是个个开源库,如:
SWR等。

上面的方案,博主有一个更完善的方案在github上, 结合了丰富的业务功能,有兴趣可以关注下(最好帮忙来个star):github.com/fridaymarke…

回复

我来回复
  • 暂无回复内容