Hi everyone
Today I wanna show you an HTTP client that I use in my projects and how it helped me during RESTful API calls.
If you are asking why I did such a thing? Well, using pure Axios is frustrating, fetch API is trash, and React Query (a.k.a TanStack Query) is just not for me.
Oh, guess what! I handle loading state as well ...
So let's how I make my HTTP API calls
MyComponent.tsx
const MyComponent = () => {
const { getProducts, dataProducts, loadingProducts } = useAxios({
url: '/url',
name: 'Products',
})
useEffect(() => {
getProducts()
}, [])
return <div>{dataProducts && <div>Show products here ...</div>}</div>
}
export default MyComponent
Very simple! You can have post requests and maybe add other methods as well. But I decided to keep it simple.
So do you need a put request?
Here is how to use it:
const { putReqByUrl } = useAxios({
url: '/url',
name: 'Products',
})
const res = await putReqByUrl('/1234')
Or maybe you have to fetch from many URLs?
Ok:
const { getReq } = useAxios({
url: '/url',
})
const { getReq: getOtherUrl } = useAxios({
url: '/other-url',
})
const { getAnotherOne, postAnotherOne } = useAxios({
url: '/other-url',
name: 'AnotherOne',
})
await getReq()
await getOtherUrl()
await getAnotherOne()
await postAnotherOne()
Yeah yeah you need queries
await getReq({ page: 2 })
// It will be
// GET method into -> your-super-url?page=2
// You can add more no problem
So this is what my custom hook looks like
useAxios.ts
import axios from 'axios'
const axiosInstance = axios.create()
axiosInstance.defaults.baseURL = 'base url here'
interface Props {
url: string
data?: any
name?: string | null
notif?: boolean
headers?: any
}
const objectToQueryString = (obj: any, withQuestionMark = true) => {
let r: any = []
Object.keys(obj).forEach((key) => {
if (obj[key] !== null && obj[key] !== undefined) {
r.push(key + `=` + obj[key])
}
})
return r.length > 0 ? `${withQuestionMark ? '?' : ''}${r.join('&')}` : null
}
const useAxios = ({
notif = true,
url,
headers,
data: userData,
name = null,
}: Props) => {
const [loading, setLoading] = useState(false)
const [data, setData] = useState(null)
const [response, setResponse] = useState({})
const [status, setStatus] = useState(0)
const [errorMessage, setErrorMessage] = useState(null)
const [error, setError] = useState(null)
// your custom alert hook if you have
// whenever you make an http request, you will have toast
// and alarm stuff
const alert = useAlert()
const request = async (
method: string,
payload = {},
noLoading = false,
userUrl?: string
) => {
setLoading(true)
const axiosObj = {
method,
headers: headers,
url: '',
data: {},
}
if (method === 'GET') {
if (objectToQueryString(payload)) {
axiosObj.url = url + objectToQueryString(payload)
} else {
axiosObj.url = url
}
} else {
axiosObj.url = url
axiosObj.data = payload
}
if (userUrl) {
axiosObj.url = userUrl
}
try {
const res = await axiosInstance(axiosObj)
setData(res.data.data)
setResponse(res)
setStatus(res.status)
setLoading(false)
// Add your alert here if you have any
if (notif) {
// TODO translate first then
// alert({
// type: 'success',
// @ts-ignore
// text: res.data.message,
// })
}
return res.data
} catch (e: any) {
setResponse(e.response)
setError(e)
setStatus(e.response.status)
setErrorMessage(e.response.data.message)
setLoading(false)
// Add your alert here if you have any
if (notif) {
// TODO translate first then
// alert({
// type: 'error',
// text: e.response.data.message,
// })
}
throw e
}
}
const getReq = async (data: any, noLoading = false, url?: string) =>
await request('GET', data, noLoading, url)
const postReq = async (data: any, noLoading = false, url?: string) =>
await request('POST', data, noLoading, url)
const putReq = async (data: any, noLoading = false, url?: string) =>
await request('PUT', data, noLoading, url)
const patchReq = async (data: any, noLoading = false, url?: string) =>
await request('PATCH', data, noLoading, url)
const deleteReq = async (data: any, noLoading = false, url?: string) =>
await request('DELETE', data, noLoading, url)
const deleteReqByUrl = (url: string) => deleteReq(null, false, url)
const putReqByUrl = (url: string, data: any) => putReq(data, false, url)
const patchReqByUrl = (url: string, data: any) => patchReq(data, false, url)
const getReqByUrl = (url: string, data: any) => getReq(data, false, url)
const postReqByUrl = (url: string, data: any) => postReq(data, false, url)
const returnObj: any = {
error,
data,
response,
status,
errorMessage,
loading,
getReq,
postReq,
putReq,
patchReq,
deleteReq,
deleteReqByUrl,
putReqByUrl,
getReqByUrl,
patchReqByUrl,
postReqByUrl,
}
// name sanitization
if (name) {
returnObj['get' + name] = getReq
returnObj['post' + name] = postReq
returnObj['put' + name] = putReq
returnObj['patch' + name] = patchReq
returnObj['delete' + name] = deleteReq
returnObj['loading' + name] = loading
returnObj['data' + name] = data
returnObj['error' + name] = error
returnObj['getByUrl' + name] = getReqByUrl
returnObj['postByUrl' + name] = postReqByUrl
returnObj['putByUrl' + name] = putReqByUrl
returnObj['patchByUrl' + name] = patchReq
returnObj['deleteByUrl' + name] = deleteReq
}
return returnObj
}
Thanks for reading guys!
And oh, you have read this post. So you can see the Vue.js version of this useAxios ;-)
Go and check it out:
Easier way of data fetching with Axios in Vue3
Top comments (0)