useAxios - React custom http client
Tags: react, axios, javascript, tutorial
Published: 2022-02-10 08:20:52


Often times we are faced with difficulty in tracking the request status while making api calls on our react app. Request status here could be the data response, loading status, error encountered, etc.
The work around is usually to create individual useState to manage all the status that we want (like error, data, etc).

>This hook is built on top of javascript [axios](https://www.npmjs.com/package/axios) package

First, let’s create the useAxios custom hooks

_//useAxios.js_
```javascript
import { useState, useEffect } from "react";
import axios from "axios";

const useAxios = props => {
  const [axiosData, setAxiosData] = useState({
    url: null,
    method: "GET",
    body: null,
    headers: null
  });
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(false);
  const [status, setStatus] = useState(null);

  const sourceToken = axios.CancelToken.source();
  const fetchApi = async () => {
    setLoading(true);
    setData(null);
    setError(null);
    setStatus(null);
    try {
      const data = axiosData?.body ? { data: axiosData?.body } : {};
      const headers = axiosData?.headers ? { headers: axiosData?.headers } : {};
      const response = await axiosClient({
        url: axiosData.url,
        method: axiosData.method ?? "GET",
        cancelToken: sourceToken.token,
        ...data,
        ...headers,
      });
      setLoading(false);
      setStatus(response?.status);
      setData(response?.data);
      if (props.onSuccess) props.onSuccess(response?.data);
    } catch (error) {
      const errorMsg = error?.message;
      setLoading(false);
      setError(String(errorMsg));
      setStatus(error?.response?.status);
      if (props.onError) props.onError(errorMsg);
    }
  };

  useEffect(() => {
    if (axiosData.url != null) {
      fetchApi();
    }
    // abort the fetch if screen is dead/inactive
    return () => sourceToken.cancel();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [axiosData]);

  // return [setPostData, data, error, loading, status];
  return { axios: setAxiosData, data, error, loading, status };
};

export default useAxios;
```
##Initialize request with useAxios

To initialize your request
 
_//index.js_
```javascript
import useAxios from "customHooks/useAxios";
const { axios, data, error, loading, status } = useAxios();
```
---
`axios: custum axios function to make the api request
data: reponse data from the endpoint
error: contains error message if an error occures
status: returns status code of the request
`

To trigger the api request, for instance when a button is clicked 
```javascript
const onClick = ()=>{
  axios({
      url: "https://example.com"
    });
}
```
This makes a get request to `https://example.com`
The axios function can accept multiple parameters like method, body, and headers

##What about POST/PATCH/DELETE requests
To make a request with a custom methods, you could do
```javascript
const onClick = ()=>{
    const data = {
      name:"Sample name",
      category:"sampleCat",
    }
    axios({
      url: "https://example.com",
      method:"POST",
      body:data,
      headers:{...}
    });
}
```
You can also also listen for success or error response while initializing the useAxios. Here is how you can do this, 
```javascript
 const { axios, data, error, loading, status } = useAxios({
    onSuccess: (data) => {
      console.log(data);
    },
    onError: (error) => {
      console.log(error);
    }
  });
```
**onSuccess** is fired when the data is returned from the endpoint 
**onError** is fired when an error occurs.

> You can as well enhance the `useAxios hook` to include `base url`, `token`, etc...

Thanks for reading!