Managing API Requests in React Native Using Axios

Learn the basics of Axios

sudhirkumar
7 min readDec 3, 2019
Photo by Verne Ho on Unsplash

Introduction

Axios is a promise-based HTTP client that works in the browser and in a node.js environment. It provides a single API for dealing with XMLHttpRequests and node’s HTTP interface. Besides that, it wraps the requests using a polyfill for ES6 new promise syntax. We can also intercept and cancel requests, and there’s built-in client-side protection against cross-site request forgery.

Using it inside a React Native project is simple! In this piece, we’ll use Axios to access the common HTTP or HTTPS API within a React Native application. We start by adding Axios to our project.

Installation Process

Just like any other library, depending on the mode of package manager you are using you can choose any one of these commands to install Axios:

 yarn add axios

npm install axios --save

Before moving to the main part let’s revise some basics. If you are a beginner please read this carefully as these are some of the basics of how you should make those API calls in your application.

Get Requests

The get method is used to execute GET requests. It takes two parameters: The endpoint and a callback function.

import React from 'react';
import axios from 'axios';

export default class Requests extends React.Component {
state = {
nameList: []
}
// make the GET request to fetch data from the URL then using promise function to handle response. componentDidMount() {
axios.get(`url`)
.then(res => {
const nameList = res.data;
this.setState({ nameList });
})
}

render() {
const {nameList} = this.state;
return (
<ul>
{
nameList.map(user => <li>{user.name}</li>)
}
</ul>
)
}
}

Post Requests

The post method is another way to post data to the server. It takes three parameters: URL, the data you want to post, and a callback function.

// Rest code is same as GET post.post('access_token', {// data to be sent
email : 'redjames@gmail.com" ,
password: '12346'
})
.then(response => {
if (response.data.status) {
console.log(response);
}
}).catch(error => {console.log(error)});

Did you just ignore it? Quite confident of you I must say.

Anyway, moving on…I’m going to give you a snapshot of how you can make multiple requests at the same time.

Handling Multiple API URLs in a Single Request

While developing the code there can be scenarios when you have to make multiple API calls in the same file and they may or may not try to fetch data at the same time. The order of the calls might result in a delay in receiving or posting data.

Here’s how you can make multiple calls at the same time using Axios.all functionality. It handles multiple API calls at the same time. If you are dealing with React Native you can easily create a function, add this code and call this in thecomponentDidMount function:

import axios from 'axios';  let one = "https://api.storyblok.com/v1/cdn/stories/health?version=published&token=wANpEQEsMYGOwLxwXQ76Ggtt" let two = "https://api.storyblok.com/v1/cdn/datasources/?token=wANpEQEsMYGOwLxwXQ76Ggtt" let three = "https://api.storyblok.com/v1/cdn/stories/vue?version=published&token=wANpEQEsMYGOwLxwXQ76Ggtt"  const requestOne = axios.get(one); 
const requestTwo = axios.get(two);
const requestThree = axios.get(three);
axios.all([requestOne, requestTwo, requestThree]).then(axios.spread((...responses) => {
const responseOne = responses[0]
const responseTwo = responses[1]
const responesThree = responses[2]
// use/access the results
})).catch(errors => {
// react on errors.
})

Managing URLs With the Common Base URL

This is the main reason I’m writing this piece. There’s always a requirement to use multiple URLs in an app with a common base URL. There are multiple methods of how you can make the API requests to fetch data from these URLs. If you’re a professional and expert let me know if there is an alternative to this — I would appreciate it!

First step

Create a config folder in your app. This folder must be inside your app project (whatever you named it). Add a file and name it config.js. Add the following code inside the file:

export const apiConfig = {baseUrl: 'https://nameofthedomain.net/api/v1/', 
// should end with a slash
clientId: '1',
clientSecret: 'xc34jamesDevV41XwKbWhrsGgHvR3hjwG8',
};
// Ask your backend expert if you have no idea about client id and clientSecret if you are new to it.

Second step

Create another folder in the app. Name it apiAuth and create three files inside it, as shown:

Check for both config and apiAuth folder

Let’s add code to the empty files you just created. You probably have an understanding from their names what they are meant for, but let’s dive on for more details.

Add the following code to guestClient.js

This file is used to make the calls that don’t require any token generation or any user management to maintain the state. These are simple URL which is globally available and have a common base. We have initiated Axios in this file and have added the base URL and headers associated with them. If there is any data to be sent you can send it as mentioned in the code below.

Interceptors are basically for the response you get from the browser after the calls are made. In this section, random calls are categorized. Those requests which don’t require any authentication or user details are called guest URLs. If you’re still confused: The guest client is for the anonymous guest that calls without any authentication and authorization.


import axios from 'axios';
import {apiConfig} from '../config/config';
const client = axios.create({
baseURL: apiConfig.baseUrl,
headers: {
Accept: 'application/json'
},
data:{
scope: '',
id: 34,
});
export default client;function getUrl(config) {
if (config.baseURL) {
return config.url.replace(config.baseURL, '');
}
return config.url;
}
// Intercept all requests
client.interceptors.request.use(
config => {
console.log(`%c ${config.method.toUpperCase()} - ${getUrl(config)}:`,'color: #0086b3; font-weight: bold',config,);
return config;
}, error => Promise.reject(error),);
// Intercept all responses
client.interceptors.response.use(
async response => {console.log(`%c ${response.status} - ${getUrl(response.config)}:`,
'color: #008000; font-weight: bold',
response,);return response;},
error => {console.log(`%c ${error.response.status} - ${getUrl(error.response.config)}:`,'color: #a71d5d; font-weight: bold',error.response,);
return Promise.reject(error);
},
);

Add the following code to loggedInClient.js

LoggedInClient, as the name suggests, consists of the APIs required after the person has logged-in and needs to make some API calls to fetch data from the server — support requests, a list of names associated with the account, or user details, for instance. All these types of requests can be made using this code:

import axios from 'axios';
import {Alert} from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
import {apiConfig} from '../config/config';
const getAccessToken = async () => {
try {
const retrievedItem = await AsyncStorage.getItem('tokenData');
if (retrievedItem !== null) {
const item = JSON.parse(retrievedItem);
console.log(item);
const authorization = `Bearer ${item.token}`;
// We have data!!
return authorization;
} return null;
} catch (error) {
// Error retrieving data
}};
const loginClient = axios.create({
baseURL: apiConfig.baseUrl,
headers: {
Accept: 'application/json',
},
});
const getLoginClient = async () => {
loginClient.defaults.headers.common.Authorization = await getAccessToken();
return loginClient;
};
export default getLoginClient;function getUrl(config) {
if (config.baseURL) {
return config.url.replace(config.baseURL, '');
}
return config.url;
}
// Intercept all requests
loginClient.interceptors.request.use(
config => {
console.log(`%c ${config.method.toUpperCase()} - ${getUrl(config)}:`,'color: #0086b3; font-weight: bold',config,);
return config;
},error => Promise.reject(error),);
// Intercept all responsesloginClient.interceptors.response.use(
async response => {if (response.status === 401) {
try {
const value = await AsyncStorage.getItem('tokenData');
if (value !== null) {
// We have data!!
AsyncStorage.clear();
NavigationService.navigate('AuthStackScreen');
}
} catch (error) {
// Error retrieving data
console.log(error, 'logged in client error');
}} console.log(`%c ${response.status} - ${getUrl(response.config)}:`,'color: #008000; font-weight: bold',response,);return response;},
error => {console.log(error, 'error console');
if (error.response.status === 429) {
Alert.alert('Too many requests. Please try again later.');
} console.log(`%c ${error.response.status} - ${getUrl(error.response.config)}:`,'color: #a71d5d; font-weight: bold',error.response,);
return Promise.reject(error);
},);

Add the following code to tokenClient.js

Token client requests are those where we need to generate and save the token in response. Examples are when we are signing up for an application or during registration.

import axios from 'axios';
import {apiConfig} from '../config/config';
const client = axios.create({
baseURL: apiConfig.baseUrl,
headers: {
Accept: 'application/json',
},
data: {
// client_id: apiConfig.clientId,
// client_secret: apiConfig.clientSecret,
id: 'password',
scope: '*',
},
});
export default client;
function getUrl(config) {
if (config.baseURL) {return config.url.replace(config.baseURL, '');}
return config.url;
}
// Intercept all requestclient.interceptors.request.use(
config => {
console.log(
`%c ${config.method.toUpperCase()} - ${getUrl(config)}:`,
'color: #0086b3; font-weight: bold',config,);
return config;
},error => Promise.reject(error),
);
// Intercept all responsesclient.interceptors.response.use(
async response => {
console.log(
`%c ${response.status} - ${getUrl(response.config)}:`,
'color: #008000; font-weight: bold',
response,
);
return response;
},
error => {
console.log(
`%c ${error.response.status} - ${getUrl(error.response.config)}:`,
'color: #a71d5d; font-weight: bold',
error.response,
);return Promise.reject(error);},);

Final step

We are done with the basic code. Now, all we need to do is call them in our files when and where they’re required.

How do we use all the code above?

Summarize the whole piece and you have your answer. Just import the file and, depending on the nature of the API, you can make POST or GET requests to send or receive the data respectively. The response is a must and can be stored and configured as desired by the developer. Check out the code for better understanding.

Importing the files

import loginRequest from '../apiAuth/tokenClient';
//Import the file if you are generating token
import getLoginClient from '../apiAuth/loggedInClient';
//Import the file if you are logged in
import guestRequest from '../apiAuth/guestClient';
//Import the file if you are using no token required API

Making requests

Here the URL is listed and a post request is made to send the data and handle the response. Note that only the endpoint is called inside the request and not the whole URL. That’s why we have come so far — please don’t make dumb mistakes of calling the whole API URL again!

import getLoginClient from '../apiAuth/loggedInClient';//The url is https://nameofthedomain.net/api/v1/contactSupportonButtonPress = async () => {
const {randomMesage} = this.state;
const client = await getLoginClient();
client
.post('contactSupport', {
message: randomMessage,
})
.then(response => {
console.log('response is', response);
})
.catch(error => {
console.log(error);});
};

The get method is called like this:

import apiClient from '../../api/loggedInClient';
//The url is https://nameofthedomain.net/api/v1/flashcards
onPress= async () => {
const client = await apiClient();
client.get('flashcards')
.then(async res => {
console.log(res);
})
.catch(error => console.log(error));
},

Conclusion

We have successfully integrated the API with a common base URL and made all types of basic request to the server.

One point to ponder here is that API calls are not limited to these two request types — there are more to explore. If you have any questions related to API handling, please feel free to get in touch. Pleasure to help. If you need the whole code please feel free to drop me an email via my website.

Keep learning and growing!
Reach out at https://www.instagram.com/navigatorkumar/

--

--