In many applications we are using low level fetch methods and making custom adjustments as we need. It works but Axios can abstract away most of the stuff that's done manually there. If we use Axios, we can handle these cases much more cleanly.
For example, Axios interceptors are much easier to set up. Also, when we import Axios, we receive a singleton. So, whatever change we make will be reflected anywhere we use Axios. T his is useful while handling headers. When logging in, we can set auth tokens in Axios headers so that we won't have to specify it for every requests. When logging out, we can reset the Axios headers.
Axios helps to keep things D.R.Y with instances, interceptors, and defaults. This can help with complex applications that are frequently making API requests.
Separate instances are often created for various APIs, interceptors are set up for global error handling, and defaults are often set, or unset, for things like common headers.
Axios’s library has a few other useful features.
1$ yarn add axios
1axios.get('/users/12345')
2 .then(response => {
3 // handle success
4 console.log(response);
5 })
6 .catch(error => {
7 // handle error
8 console.log(error);
9 })
10 .then(() => {
11 // always executed
12 });
It is suggested to add following configurations in componentDidMount
of App.jsx
so that the axios instance is prepared to be used throughout the app.
1import axios from 'axios';
2import { getCSRFToken } from 'components/utils';
3
4axios.defaults.baseURL = 'https://example.com/api/v1/';
5axios.defaults.timeout = 1000;
6axios.defaults.headers.common['X-CSRF-Token'] = getCSRFToken();
7
8axios.get('/users/12345')
9 .then(response => {
10 console.log(response);
11 });
This could be useful for making different API calls which may not be done from the default instance. For example: External services etc.
1import axios from 'axios';
2import { getCSRFToken } from 'components/utils';
3
4const API = axios.create({
5 baseURL: 'https://example.com/api/v1/',
6 timeout: 1000,
7 headers: {
8 'X-CSRF-Token': getCSRFToken()
9 }
10});
11
12API.get('/users/12345')
13 .then(response => {
14 console.log(response);
15 });
requests
to add auth headers1const requestHandler = request => {
2 request.headers['Authorization'] = getAuthHeader();
3
4 return request;
5}
6
7axios.interceptors.request.use(request => requestHandler(request));
responses
to log errors1// Provide only response json part
2// => Chuk other metadata provided by axios
3const responseSuccessHandler = response => {
4 return response.data;
5};
6
7// Log & Sanitize errors response
8// => The errors given by server will not be always consistent so we
9// could sanitize the response and return proper error to the client.
10const responseErrorHandler = error => {
11 var errors = ["Something went wrong, please try again!"];
12
13 if (error.response) {
14 if (error.response.data.errors)
15 errors = error.response.data.errors;
16 if (error.response.data.error)
17 errors = [error.response.data.error];
18
19 if (error.response.status === 401)
20 forceLogoutUser();
21 } else if (error.request) {
22 console.log(error.request);
23 } else {
24 console.log('Error', error.message);
25 }
26
27 return Promise.reject({
28 status: error.response.status,
29 errors: errors
30 });
31}
32
33axios.interceptors.response.use(
34 response => responseSuccessHandler(response),
35 error => responseErrorHandler(error)
36);
Axios simplifies and abstracts away a lot of code for us. Here are some useful abstractions that axios provides to us.
Axios is based on XMLHttpRequest and consequently all the events, properties and methods that come along with it are available in Axios. A well known fact(nitpick) about fetch() is that it doesn't provide a method to track upload progress. Axios provides very easy ways to track upload progress on the other hand.
Here is an example from the axios repo itself:
1const [uploadProgress, setUploadProgress] = useState(0); // display uploadProgress value in a loader
2// other lines of code
3// .......
4
5const config = {
6 onUploadProgress: progressEvent => {
7 const percentCompleted = Math.round( (progressEvent.loaded * 100) / progressEvent.total );
8 setUploadProgress(percentCompleted);
9 }
10 };
11
12 try {
13 const updatedBlog = axios.put('/upload/server', data, config);
14 return updatedBlog.response.data;
15 } cactch(err) {
16 if(!err.response) {
17 throw err;
18 }
19 throw err.response.data;
20 }
As shown earlier setting timeout is as easy as adding a timeoout: 3000
key-value pair to the axios config object.
fetch() provides the AbortController interface for timeouts, but it is not as simple to implement as in axios.
You can also implement your own higher-order function and make the fetch call inside the returned function.