问题
I am trying to present a simple user list from an API which returns this:
[{"UserID":2,"FirstName":"User2"},{"UserID":1,"FirstName":"User1"}]
I do not understand fully how to handle Axios responses with types. The Typescript error is
Type '{} | { id: number; firstName: string; }' is not assignable to type 'IntrinsicAttributes & UserListProps & { children?: ReactNode; }'.
Property 'items' is missing in type '{}' but required in type 'UserListProps'.
from the <UserList />
element in the Users.tsx
file below. Is my User
interface wrong?
import React, {useEffect, useState, Fragment } from 'react';
import UserList from './UserList';
import axios, {AxiosResponse} from 'axios';
interface User {
id: number;
firstName: string;
}
const Users: React.FC = (props) => {
const [users, setUserList] = useState<User>();
useEffect(() => {
// Use [] as second argument in useEffect for not rendering each time
axios.get('http://localhost:8080/admin/users')
.then((response: AxiosResponse) => {
console.log(response.data);
setUserList( response.data );
});
}, []);
return (
<Fragment>
<UserList {...users} />
</Fragment>
);
};
export default Users;
Below is my UserList.tsx
.
import React, {Fragment } from 'react';
interface UserListProps {
items: {id: number, firstName: string}[];
};
const UserList: React.FC<UserListProps> = (props) => {
return (
<Fragment>
<ul>
{props.items.map(user => (
<li key={user.id}>
<span>{user.firstName}</span>
{/* not call delete function, just point to it
// set this to null in bind() */}
</li>
))}
</ul>
</Fragment>
);
};
export default UserList;
回答1:
There is generic get method defined in axios/index.d.ts
get<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): 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 );
});
--Edit
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>
);
};
回答2:
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 incorrect type argument when you useState
to create the array of users.
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 type argument
const [users, setUserList] = useState<TUserList>();
useEffect(() => {
// Use [] as 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 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>
{/* not call delete function, just point to it
// set this to null in bind() */}
</li>
))}
</ul>
</Fragment>
);
};
export default UserList;
来源:https://stackoverflow.com/questions/62217642/react-and-typescript-which-types-for-axios-response