Api wrappers using Axios, Fetch.
Tags: axios, fetch, javascript, api
Published: 2022-10-01 20:25:09

## 1. Axios api wrapper 
`urls.js`

```
export const API_BASE_URL = 'https://jsonplaceholder.typicode.com';

export const getApiUrl = (endpoint) => API_BASE_URL + endpoint;

export const POSTS = getApiUrl('/posts');
export const DELETE_POSTS = getApiUrl('/todos/');
```
`utils.js`

```
import axios from 'axios';
import AsyncStorage from '@react-native-async-storage/async-storage';
import store from '../redux/store';
import types from '../redux/types';

const { dispatch, getState } = store;

export async function getHeaders() {
    let userData = await AsyncStorage.getItem('userData');
    if (userData) {
        userData = JSON.parse(userData);
        //console.log(userData.accessToken, 'header')
        return {
            authorization: `${userData.access_token}`,
        };
    }
    return {};
}

export async function apiReq(
    endPoint,
    data,
    method,
    headers,
    requestOptions = {}
) {

    return new Promise(async (res, rej) => {
        const getTokenHeader = await getHeaders();
        headers = {
            ...getTokenHeader,
            ...headers
        };

        if (method === 'get' || method === 'delete') {
            data = {
                ...requestOptions,
                ...data,
                headers
            };
        }

        axios[method](endPoint, data, { headers })
            .then(result => {
                const { data } = result;

                if (data.status === false) {
                    return rej(data);
                }

                return res(data);
            })
            .catch(error => {
                console.log(error)
                console.log(error && error.response, 'the error respne')
                if (error && error.response && error.response.status === 401) {
                    clearUserData();
                    // NavigationService.resetNavigation();
                    //NavigationService.navigate('LoginPage');
//                     dispatch({
//                         type: types.CLEAR_REDUX_STATE,
//                         payload: {}
//                     });
//                     dispatch({
//                         type: types.NO_INTERNET,
//                         payload: { internetConnection: true },
//                     });


                }
                if (error && error.response && error.response.data) {
                    if (!error.response.data.message) {
                        return rej({ ...error.response.data, msg: error.response.data.message || "Network Error" })
                    }
                    return rej(error.response.data)
                } else {
                    return rej({ message: "Network Error", msg: "Network Error" });
                }
            });
    });
}

export function apiPost(endPoint, data, headers = {}) {
    return apiReq(endPoint, data, 'post', headers);
}

export function apiDelete(endPoint, data, headers = {}) {
    return apiReq(endPoint, data, 'delete', headers);
}

export function apiGet(endPoint, data, headers = {}, requestOptions) {
    return apiReq(endPoint, data, 'get', headers, requestOptions);
}

export function apiPut(endPoint, data, headers = {}) {
    return apiReq(endPoint, data, 'put', headers);
}

export function setItem(key, data) {
    data = JSON.stringify(data);
    return AsyncStorage.setItem(key, data);
}

export function getItem(key) {
    return new Promise((resolve, reject) => {
        AsyncStorage.getItem(key).then(data => {
            resolve(JSON.parse(data));
        });
    });
}


export async function clearUserData() {
    return AsyncStorage.removeItem('userData');
}

```
**USAGE:**
`action.js`

```
import { DELETE_POSTS, POSTS } from "../../config/urls"
import { apiDelete, apiGet } from "../../utils/utils"


export function getPosts() {
    return apiGet(POSTS)
}

export function deletePost(id) {
    return apiDelete(DELETE_POSTS + `${id}`)
}
```

---

## 2. Fetch api wrapper:

```
import { stringify } from 'query-string';

export const sendRequest = ({
  url,
  method,
  useCredentials=false,
  body,
  headers = {},
  queryParams = {}
}) => {
  const options = {
    method: method,
    headers: new Headers({ 'content-type': 'application/json', ...headers }),// by default setting the content-type to be json type
    body: body ? JSON.stringify(body) : null
  };
  if (useCredentials) options.credentials = "include";
  if (queryParams) {
    url = `${url}?${stringify(queryParams)}`;
  }

  return fetch(url, options).then(res => {
    if (res.ok) {
      return res.json();
    } else {
      return res.json().then(function(json) {
        // to be able to access error status when you catch the error 
        return Promise.reject({
          status: res.status,
          ok: false,
          message: json.message,
          body: json
        });
      });
    }
  });
};
```
sendRequest method accepts url(String), method: GET, POST, PUT, DELETE(String), useCredentials(boolean) which is if you want the server to read the session cookie(it sets credentials=’include’), body, headers and simple queryParams object.

By default the above wrapper sets ‘content-type’ key in the headers to ‘application/json’. You can provide your own headers and they will overwrite the exisiting ones.

You can use the above wrapper this way:

```
const url = "yourUrlHere";
  sendRequest({
    url,
    method: 'GET',
    useCredentials: true,
    queryParams: {
      offset,
      limit
    }
  })
  .then((res) => alert("Got my feed!!!"))
  .catch((err) => alert(`status: ${err.status} ${err.message}`));
```