ค้นหาเว็บไซต์

reactjs - React และ TypeScript—ประเภทไหนสำหรับการตอบสนองของ Axios?


ฉันกำลังพยายามแสดงรายการผู้ใช้ง่าย ๆ จาก API ซึ่งส่งค่าดังนี้:

[{"UserID":2,"FirstName":"User2"},{"UserID":1,"FirstName":"User1"}]

ฉันไม่เข้าใจอย่างเต็มที่ว่าต้องจัดการกับการตอบสนองของ Axios พร้อมชนิดข้อมูลอย่างไร ข้อผิดพลาดของ TypeScript คือ

ประเภท ' {} | { id: number; firstName: string; } ' ไม่สามารถกำหนดค่าให้กับประเภท ' IntrinsicAttributes & UserListProps & { children?: ReactNode; } ' ได้.

คุณสมบัติ 'items' หายไปในประเภท '{}' แต่จำเป็นในประเภท 'UserListProps'

จากองค์ประกอบ <UserList /> ในไฟล์ Users.tsx ด้านล่าง อินเทอร์เฟซ User ของผมผิดหรือไม่?

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;

ด้านล่างนี้คื่อ 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

มีเมธอดทั่วไป get ที่ถูกกำหนดไว้ใน axios/index.d.ts

get<T = never, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig<T>): Promise<R>;

ตัวอย่าง

interface User {
    id: number;
    firstName: string;
}


axios.get<User[]>('http://localhost:8080/admin/users')
        .then(response => {
            console.log(response.data);
            setUserList( response.data );
        });

ฉันคิดว่าคุณกำลังส่งรายการไปยังคอมโพเนนต์ลูกในทางที่ผิด

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

คุณต้องระบุอาร์กิวเมนต์ประเภทเมื่อเรียกใช้งาน axios.get หากคุณไม่ต้องการให้ Axios ประเมินประเภทสำหรับค่าของ response เป็น any

และคุณกำลังส่งอาร์กิวเมนต์ประเภทไม่ถูกต้องเมื่อคุณ useState เพื่อสร้างอาร์เรย์ของผู้ใช้

วิธีที่ถูกต้อง

interface User {
  id: number;
  firstName: string;
}

// Initialized as an empty array
const [users, setUserList] = useState<User[]>([]); // 'users' will be an array of users

ตัวอย่างเช่น,

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;

หากคุณเลือกที่จะส่งออกชนิด type TUserList=User[] คุณสามารถใช้มันในคอมโพเนนต์ UserList ของคุณเป็นชนิดของ props ได้ ตัวอย่างเช่น,

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;

บทความที่เกี่ยวข้อง