HTTP client: axios and react fetch

David Zhao
4 min readJul 22, 2021

--

axios⁰.21.1, React¹⁷.0.2, Http Client, Created at July 21, 2021, Read Series…

Chose axios as http client. A React built-in fetch() http client demo also included.
Sample public/todos.json data

Overall they are very similar. Some benefits of axios:
— Transformers: allow performing transforms on data before request is made or after response is received
- Interceptors: allow you to alter the request or response entirely (headers as well). also perform async operations before request is made or before Promise settles
- Built-in XSRF protection

npm install axios
npm install --save @types/qs

axio config in src/apis/todoApiConfig.ts

[Try to understand] axio config in todoApiConfig and PathLike and qs. todoApiConfig is AxiosRequestConfig.

import * as qs from "qs";
import { PathLike } from "fs";
export const todoApiConfig = {
returnRejectedPromiseOnError: true,
withCredentials: true,
timeout: 30000,
baseURL: "",
headers: {
common: {
"Cache-Control": "no-cache, no-store, must-revalidate",
Pragma: "no-cache",
"Content-Type": "application/json",
Accept: "application/json",
'Access-Control-Allow-Origin': '*',
},
},
paramsSerializer: (params: PathLike) => qs.stringify(params, { indices: false }),
}

[Try to understand] Axios config baseURL, timeout. The timeout here is http call timeout. Api Server Connection timeout should be configured in constructor in src/framework/Axios.ts

import axios, { AxiosInterceptorManager, AxiosRequestConfig, AxiosResponse } from 'axios';export class Axios {
public interceptors: {
/**
* The **Request** interceptor will be call rigth before the
`http request`
* @summary
* This a useful method especially if you need to send a
token on each request.
*/
request: AxiosInterceptorManager<AxiosRequestConfig>;
/**
* The **Response** interceptor will be call rigth before
the `http request` is received.
* @summary
* This a useful method especially if you need to send a
token on each request.
*/
response: AxiosInterceptorManager<AxiosResponse>;
};
constructor(config: AxiosRequestConfig) {
axios.defaults.timeout = config.timeout;
axios.defaults.httpAgent =
new http.Agent({ timeout: config.timeout });
axios.defaults.httpsAgent =
new http.Agent({ timeout: config.timeout });
return axios.create(config);
}
}

How to Use Axios/Typescript like a pro! (axios-es6-class)

Ernesto Jara Olveda provided excellent solution on how to use axios in es6 class. Click upper link to read the solution.
Original Axios.ts is src/framework/Axios.ts, it is the wrapper class of axios.
Original api.ts is src/framework/ApiBase.ts, it is the base class:

  • interceptors.request/response in constructor
  • Methods of all HTTP request types: GET/PUT/POST/DELETE/PATCH, HEAD/OPTIONS, and generic request method.
  • success<T>()/error<T>() generic event handlers
  • getToken(), setToken(), getUri()

Model example in src/models/Todo.ts

[Try to understand] React is more like MVVM. ToDo interface is used in Apis and Views.
[Try to understand] ‘as unknown as Todo’

export interface Todo {
id: string,
completed: boolean
text: string,
}
export function createTodoDefault(): Todo {
return {
id: 0,
text: '',
completed: false,
} as unknown as Todo;
}

Concrete Api class example in src/apis/TodoApi.ts

[Try to understand] TodoApi extends ApiBase. and exports todoApi instance, with todoApiConfig, utilized in src/features/Todo/ListWithAxios.tsx.

[Try to understand] todoApiConfig, TodoApi, todoApi, getList(), and AxiosRequestConfig, AxiosResponse, Promise<Todo[]>, and this.interceptors.request and this.interceptors.response.

import { AxiosRequestConfig, AxiosResponse } from "axios";
import { ApiBase } from "src/framework/ApiBase";
import { Todo } from "src/models/Todo";
import { todoApiConfig } from "./todoApiConfig";
export class TodoApi extends ApiBase {
constructor(config: AxiosRequestConfig) {
// NEVER FORGET THE SUPER
super(config);
// this middleware called right before the http request is made.
this.interceptors.request.use((param: AxiosRequestConfig) => ({
...param,
}));
// this middleware is been called right before the response is get it by the method that triggers the request
this.interceptors.response.use((param: AxiosResponse) => ({
...param
}));this.getList = this.getList.bind(this);
}
public getList = (): Promise<Todo[]> => {
const url = '/todos.json';
return this.get<Todo[], AxiosResponse<Todo[]>>(url)
.then(this.success);
}
}
export const todoApi = new TodoApi(todoApiConfig);

Axio Api call in src/features/Todo/ListWithAxios.tsx

[Try to understand] todoApi.getList().then in useEffect
[Try to understand] todoList && todoList.map((item: Todo) to render a list
[Try to understand] <Typography key={item.id}>, each item in a UI list reqires a key field.

import { Accordion, AccordionDetails, AccordionSummary, Typography } from '@material-ui/core';
import { ExpandMore } from '@material-ui/icons';
import { useEffect, useState } from 'react';
import { todoApi } from 'src/apis/TodoApi';
import { Todo } from 'src/models/Todo';
export default function ListWithAxios(): JSX.Element {
const [todoList, setTodoList] = useState<Todo[]>([]);
useEffect(() => {
todoApi.getList().then((result) => {
setTodoList(result);
});
// console.log('component mounted!')
}, [])
return (
<div>
<Accordion>
<AccordionSummary
expandIcon={<ExpandMore />}
aria-controls="panel2a-content"
id="panel2a-header"
>
<Typography>Basic 1.7.1. get todo List
using axios</Typography>
</AccordionSummary>
<AccordionDetails>
{todoList && todoList.map((item: Todo) => {
return (
<Typography key={item.id}>
{item.id} - {item.completed} - {item.text}
</Typography>
)
})}
</AccordionDetails>
</Accordion>
</div>
);
}

fetch() in src/features/Todo/ListWithReactFetch.tsx

[Try to understand] fetch(‘/todos.json’).then in useEffect
[Try to understand] todoList && todoList.map((item: Todo) to render a list
[Try to understand] <Typography key={item.id}>, each item in a UI list reqires a key field.

import { Accordion, AccordionDetails, AccordionSummary, Typography } from '@material-ui/core';
import { ExpandMore } from '@material-ui/icons';
import { useEffect, useState } from 'react';
import { Todo } from 'src/models/Todo';
export default function ListWithReactFetch(): JSX.Element {
const [todoList, setTodoList] = useState<Todo[]>([]);
useEffect(() => {
fetch('/todos.json')
.then(response => response.json())
.then(result=>{setTodoList(result);});

// console.log('component mounted!')
}, [])
return (
<div>
<Accordion>
<AccordionSummary
expandIcon={<ExpandMore />}
aria-controls="panel2a-content"
id="panel2a-header"
>
<Typography>Basic 1.7.2. get todo List using react fetch</Typography>
</AccordionSummary>
<AccordionDetails>
{todoList && todoList.map((item: Todo) => {
return (
<Typography key={item.id}>
{item.id} - {item.completed} - {item.text}
</Typography>
)
})}
</AccordionDetails>
</Accordion>
</div>
);
}

Github commits is here: Basic-1.7. axios and react fetch

Conclusion

Choseaxios: Overall they are very similar. Some benefits of axios:

- Transformers: allow performing transforms on data before a request is made or after a response is received

-Interceptors: allow you to alter the request or response entirely (headers as well). also, perform async operations before a request is made or before Promise settles

-Built-in XSRF protection

An comparison table from https://www.javascriptstuff.com/ajax-libraries/:

--

--

David Zhao

Expert on .Net, React, React Native . Professional on Asp.Net Mvc/Web Api, C#, React, Typescript, Maui, Html, Css, Sql Server/Oracle.