Managing API Requests in React Native Using Axios
Learn the basics of Axios
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 slashclientId: '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:
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 tokenimport getLoginClient from '../apiAuth/loggedInClient';
//Import the file if you are logged inimport 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/flashcardsonPress= 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/