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)