Saturday, May 11, 2024
 Popular · Latest · Hot · Upcoming
111
rated 0 times [  118] [ 7]  / answers: 1 / hits: 7900  / 3 Years ago, wed, may 5, 2021, 12:00:00

This is my first question, so let me know how I can improve.


I have the following axios fetch function:


export enum RequestMethod {
GET = 'GET',
POST = 'POST',
PUT = 'PUT',
PATCH = 'PATCH',
DELETE = 'DELETE',
}

export const fetchAxiosAPI = async (
url: string,
method: RequestMethod,
data = {},
options = {}
) => {
let result;
try {
result = await axios({
method,
url: `${process.env.REACT_APP_API_URL}/${url}`,
data,
...options,
validateStatus: () => {
return true;
},
}).then(response => response.data);
} catch (err) {
return null;
}
const errorStatus = result.error.status;
if (errorStatus === 401) {
localStorage.removeItem('access_token');
history.push('/login');
}
if (errorStatus === 404) {
history.replace(NOT_FOUND);
}
if (errorStatus === 500) {
history.replace(INTERNAL_SERVER_ERROR);
}
return result;
};

It looks ugly, uses await and then (which we shouldn't use).
I have two questions:



  1. How can I pass a typescript generic into this function as a parameter that will infer typescript typings for the response of API call (Promise)? I found and example using axios[methodName] like:



axios.get<User[]>(url)



But haven't found a method to pass generic using general axios method like provided in my code example.



  1. How to handle error statuses, catch block and await/then - use 1 of them? Basically, how to rewrite fetchAxiosAPI function.


More From » reactjs

 Answers
4

If I'm reading the documentation and index.d.ts file correctly, axios.request should do it. From the docs:



For convenience aliases have been provided for all supported request methods.


axios.request(config)


...



and in index.d.ts:



export interface AxiosInstance {
(config: AxiosRequestConfig): AxiosPromise;
(url: string, config?: AxiosRequestConfig): AxiosPromise;
defaults: AxiosRequestConfig;
interceptors: {
request: AxiosInterceptorManager<AxiosRequestConfig>;
response: AxiosInterceptorManager<AxiosResponse>;
};
getUri(config?: AxiosRequestConfig): string;
request<T = any, R = AxiosResponse<T>> (config: AxiosRequestConfig): Promise<R>;
get<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>;
delete<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>;
head<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>;
options<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>;
post<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R>;
put<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R>;
patch<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R>;
}

export interface AxiosStatic extends AxiosInstance {
create(config?: AxiosRequestConfig): AxiosInstance;
Cancel: CancelStatic;
CancelToken: CancelTokenStatic;
isCancel(value: any): boolean;
all<T>(values: (T | Promise<T>)[]): Promise<T[]>;
spread<T, R>(callback: (...args: T[]) => R): (array: T[]) => R;
isAxiosError(payload: any): payload is AxiosError;
}

declare const axios: AxiosStatic;


Notice that request just accepts the config object like the axios function itself does, but unlike axios it has the generic type parameters you've seen used on get, post, and such.


So something like this, see *** comments:


export const fetchAxiosAPI = async <T>(
// ^^^−−−−−−−−−−− *** type parameter
url: string,
method: RequestMethod,
data = {},
options = {}
) => {
let result: T;
try {
// *** Get the response using `axios.request` with the type argument
const response = await axios.request<T>({
method,
url: `${process.env.REACT_APP_API_URL}/${url}`,
data,
...options,
validateStatus: () => {
return true;
},
});
// *** Get the result
result = response.data;
} catch (err) {
return null; // *** This is poor practice; allow the error to propagate
// or throw a new error
}
const errorStatus = result.error.status;
if (errorStatus === 401) {
localStorage.removeItem('access_token');
history.push('/login');
}
if (errorStatus === 404) {
history.replace(NOT_FOUND);
}
if (errorStatus === 500) {
history.replace(INTERNAL_SERVER_ERROR);
}
return result;
};

[#1397] Monday, April 26, 2021, 3 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
lucianom

Total Points: 601
Total Questions: 98
Total Answers: 109

Location: Kenya
Member since Fri, Dec 23, 2022
1 Year ago
lucianom questions
Tue, Feb 22, 22, 00:00, 2 Years ago
Sun, Jan 24, 21, 00:00, 3 Years ago
Sat, Aug 15, 20, 00:00, 4 Years ago
Mon, Jun 22, 20, 00:00, 4 Years ago
Tue, Feb 18, 20, 00:00, 4 Years ago
;