base type
export interface IBaseRes<R> {
result: number
res_info: string
result_rows: R
}
api function
import { IBaseRes } from './typing'
export interface IReqProps {
uid: string
}
export interface IResProps {
uid: string
name: string
age: number /* */
}
type IReqFun<T, U> = (params?: T) => Promise<IBaseRes<U>>
export const queryUserByUid: IReqFun<IReqProps, IResProps> = (params) =>
new Promise((resolve) =>
setTimeout((=> {
resolve({
result: 0,
res_info: 'ok',
result_rows: {
uid: params.uid,
name: 'xiaoming',
age: 20,
},
})
}, 2000)
)
export default {}
注:api function若只用于useFetch,可不写类型,在useFetch时传入对应类型即可。但若可能直接调用,则需要加上类型
useFetch
/* eslint-disable no-alert */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable no-unused-vars */
import { useCallback, useState } from 'react'
import { IBaseRes } from './typing'
type IStatus = 'loading' | 'success' | 'fail' | 'standby'
/**
* <T : 接口入参, U: 接口出参>
* @param IReqFun
* @returns
*/
const useFetch = <T, U>(props: {
excuteFn:
| ((params?: T) => Promise<IBaseRes<U>>)
| ((params?: T) => Promise<any>)
| ((params?: any) => Promise<IBaseRes<U>>)
| ((params: any) => Promise<any>)
}): {
data: U
status: IStatus
excute: (params?: T) => void
} => {
const { excuteFn } = props
const [data, setData] = useState({} as U)
const [status, setStatus] = useState<IStatus>('standby')
const excute = useCallback(
async (params) => {
setStatus('loading')
try {
let res = await excuteFn(params)
const { result, res_info, result_rows } = res
if (result !== 0) {
setStatus('fail')
return
}
setData(result_rows)
setStatus('success')
} catch (e) {
setStatus('fail')
}
},
[excuteFn]
)
return {
excute,
status,
data,
}
}
export default useFetch
demo
import React, { useEffect } from 'react'
import { queryUserByUid, IReqProps, IResProps } from './api'
import useFetch from './useFetch'
const Demo: React.FC = () => {
const { data, status, excute } = useFetch<IReqProps, IResProps>({
excuteFn: queryUserByUid,
})
useEffect(() => {
excute({
uid: '1',
})
}, [excute])
return (
<div>
{status === 'success' && (
<>
<span>{data.uid}</span>
<span>{data.name}</span>
<span>{data.age}</span>
</>
)}
</div>
)
}
export default Demo