There is generic get method defined in axios/index.d.ts
get<T = never, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig<T>): Promise<R>;
Example
interface User {
id: number;
firstName: string;
}
axios.get<User[]>('http://localhost:8080/admin/users')
.then(response => {
console.log(response.data);
setUserList( response.data );
});
I think you are passing list the wrong way to child component.
const [users, setUserList] = useState<User[]>([]);
<UserList items={users} />
interface UserListProps {
items: User[];
};
const UserList: React.FC<UserListProps> = ({items}) => {
return (
<Fragment>
<ul>
{items.map(user => (
<li key={user.id}>
<span>{user.firstName}</span>
</li>
))}
</ul>
</Fragment>
);
};
Answer from Józef Podlecki on Stack OverflowThere is generic get method defined in axios/index.d.ts
get<T = never, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig<T>): Promise<R>;
Example
interface User {
id: number;
firstName: string;
}
axios.get<User[]>('http://localhost:8080/admin/users')
.then(response => {
console.log(response.data);
setUserList( response.data );
});
I think you are passing list the wrong way to child component.
const [users, setUserList] = useState<User[]>([]);
<UserList items={users} />
interface UserListProps {
items: User[];
};
const UserList: React.FC<UserListProps> = ({items}) => {
return (
<Fragment>
<ul>
{items.map(user => (
<li key={user.id}>
<span>{user.firstName}</span>
</li>
))}
</ul>
</Fragment>
);
};
You need to provide a type argument when calling axios.get if you do not want Axios to infer the type for the value response as any.
And you are passing an incorrect type argument when you useState to create the array of users.
The correct way
interface User {
id: number;
firstName: string;
}
// Initialized as an empty array
const [users, setUserList] = useState<User[]>([]); // 'users' will be an array of users
For example,
import React, {useEffect, useState, Fragment } from 'react';
import UserList from './UserList';
import axios from 'axios';
interface User {
id: number;
firstName: string;
}
// You can export the type TUserList to use as -
// props type in your `UserList` component
export type TUserList = User[]
const Users: React.FC = (props) => {
// You can also use User[] as a type argument
const [users, setUserList] = useState<TUserList>();
useEffect(() => {
// Use [] as a second argument in useEffect for not rendering each time
axios.get<TUserList>('http://localhost:8080/admin/users')
.then((response) => {
console.log(response.data);
setUserList(response.data);
});
}, []);
return (
<Fragment>
<UserList {...users} />
</Fragment>
);
};
export default Users;
If you choose to export the type type TUserList = User[], you can use it in your UserList component as the type for props. For example,
import React, {Fragment } from 'react';
import { TUserList } from './Users';
interface UserListProps {
items: TUserList // Don't have to redeclare the object again
};
const UserList: React.FC<UserListProps> = (props) => {
return (
<Fragment>
<ul>
{props.items.map(user => (
<li key={user.id}>
<span>{user.firstName}</span>
{ /* Do not call the delete function. Just point
to it. Set this to null in bind(). */}
</li>
))}
</ul>
</Fragment>
);
};
export default UserList;
How to Type Axios.js 'AxiosResponse' data generic
Typescript With Axios Response - Stack Overflow
Typescript + axios: return the subset of response
reactjs - How to solve TypeScript error with axios response in React app - Stack Overflow
Videos
Hi all!
I'm using the axios http library for Node to make requests to a public API as follows:
const response = await axios.get(url) logPaginatedResponse(response)
After receiving a response and storing it in the response variable above, I am passing the variable to the logPaginatedResponse function to log the response to the console.
My logPaginatedResponse function looks like this:
import { AxiosResponse } from "axios"
export const logPaginatedResponse = async (response: AxiosResponse) => {
console.dir({
total_records: response.data.meta.pagination.total,
records_per_page: response.data.meta.pagination.per_page,
current_page: response.data.meta.pagination.current_page,
total_pages: response.data.meta.pagination.total_pages,
})
}
The AxiosResponse interface looks like this:
export interface AxiosResponse<T = any> {
data: T;
status: number;
statusText: string;
headers: any;
config: AxiosRequestConfig;
request?: any;
}
In the logPaginatedResponse, I am trying to get autocompletion for response.data.meta.pagination.total, response.data.meta.pagination.per_page, etc.
The AxiosResponse interface gives me autocompletion for response, but no autocompletion for anything in the data object.
The problem is, the data object on the response could be one of many interfaces. See below:
interface CustomerResponse {
data: {
customer_id: number
},
meta: {
pagination: {
total: number,
count: number,
per_page: number,
current_page: number,
total_pages: number,
links: {
previous: string,
current: string,
next: string
}
}
},
}
interface ProductResponse {
data: {
product_id: number
},
meta: {
pagination: {
total: number,
count: number,
per_page: number,
current_page: number,
total_pages: number,
links: {
previous: string,
current: string,
next: string
}
}
},
}
export const logPaginatedResponse = async (response: AxiosResponse<CustomerResponse | ProductResponse>) => { // console.dir here }
Is there any way to give logPaginatedResponse either the CustomerResponse or ProductResponse interface dynamically?
I tried passing CustomerResponse or ProductResponse to the logPaginatedResponse function at the time of function invocation as follows:
const response = await axios.get(url) logPaginatedResponse<CustomerResponse>(response)
But that isn't doing the trick. Is this not possible? It almost sounds like I'm looking for what this SO post describes: https://stackoverflow.com/a/50512697 but I'm not entirely sure.
Any suggestions would be super appreciated!! Thank you so much.
EDIT:
I ended up refactoring per u/__gc's suggestion in the comments
After some re-work, I landed on using axios.get and was able to get it all worked out.
export interface Args {
curr: string;
uuid: string;
rate: string;
}
export interface Response {
curr: string;
uuid: string;
rate: {
curr: string;
type: string;
}
}
async function getSource({ curr, uuid, rate }: Args): Promise<AxiosResponse<Response>['data']> {
try {
const response = await axios.get<{ data: Response[] }>('/url');
return response.data.data[0];
} catch (err) {
throw new Error('error');
}
}
Don't know what exactly you are looking for but this might help you. Playground link: Playground
async function getSource({ curr, uuid, rate }: Source): Promise<AxiosResponse<Response>> {
const requestConfig: AxiosRequestConfig = {
method: 'get',
url: '/url',
};
try {
const response: AxiosResponse<Response> = await axios(requestConfig); //funtion expects <AxiosResponse<Response>> as return.
return response;
} catch (err) {
throw new Error('error');
}
}
Hi all, Noobie here,
So, I am using axios with typescript. I am calling get method on the axios and it returns whole bunch of data but I only need fraction of those data as following:
Interface IApiResponse{ // Small punch of types API returns name:strong Age:number } const response = axios.get<IApiResponse>(URL)
Now, my noob question is why is the response contains additional data as well; one which is not defined in the IApiResponse. For example, API response contains address as well but I have not defined that type in IApiResponse.
How can I only select few data that I need to be included in interface?
Thank you for the help ☺️☺️