HTTP client: axios and react fetch
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
Chose
axios
: 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/: