axios 使用来自REST API而不是JSON文件的数据时,可排序表为空

nzkunb0c  于 2023-10-18  发布在  iOS
关注(0)|答案(1)|浏览(103)

我正在构建我的第一个React项目,并从创建一个可排序的表开始。对于内容,我创建了一个本地JSON文件并填充了数据,使用一些在线教程来构建表元素并实现排序。到目前为止一切都很好
接下来,我想切换到从REST API而不是本地文件获取表内容。我可以检索数据没有任何问题,如果我禁用排序表内容呈现罚款。但是,如果我尝试使用排序逻辑,结果是表中根本没有数据。
我的App很简单:

mport HardwaresTable from "./tc/HardwaresTable";

const App = () => {

    return (
        <div className="table_container">
            <HardwaresTable/>
        </div>
    );
};

export default App;

HardwaresTable组件定义列并检索数据:

import Table from "../components/Table";
import testHardwares from "../test/hardwares.json";
import TableHead from "../components/TableHead";
import TableBody from "../components/TableBody";
import {useSortableTable} from "../util/useSortableTable";
import {useEffect, useState} from "react";
import axios from "axios";

const HardwaresTable = () => {
    const hardwaresColumns = [
        { label: "ID", accessor: "id", sortable: true, sortByOrder: "asc", type: "int" },
        { label: "Hardware Name", accessor: "hardwareName", sortable: false, type: "string" },
        { label: "Display Name", accessor: "displayName", sortable: true, type: "string" },
        { label: "Hardware Make", accessor: "hardwareMake", sortable: true, type: "enum" },
        { label: "Hardware Type", accessor: "hardwareType", sortable: true, type: "enum" },
        { label: "Multiplier", accessor: "multiplier", sortable: true, type: "double" },
        { label: "Average PPD", accessor: "averagePpd", sortable: true, type: "int" },
    ];

    const [loadingData, setLoadingData] = useState(true);
    const [hardwares:[], setHardwares] = useState([]);

    useEffect(() => {
        async function getData() {
            await axios
                .get("https://internal.axihub.ca/folding/hardware")
                .then((response) => {
                    // console.log(response.data);
                    setHardwares(response.data);
                });
        }
        if (loadingData) {
            getData()
                .then(r => {
                    setLoadingData(false)
                });
        }
    }, []);

    //// 'hardwares' has all content correctly here ////
    const [tableData, handleSorting] = useSortableTable(hardwares, hardwaresColumns);
    //// After calling 'useSortableTable()', 'tableData' is empty ////

    return (
        <table className="table">
            <caption>Hardwares on the system</caption>
            <TableHead columns={hardwaresColumns} handleSorting={handleSorting} />
            {loadingData ? "" : <TableBody tableData={tableData} columns={hardwaresColumns} />}
        </table>
    );
};

export default HardwaresTable;

而useSortableTable逻辑似乎是导致问题的原因;如果我不使用这个逻辑(只是将数据从REST响应直接传递到TableBody组件),数据确实加载良好:

import {useState} from "react";

function getDefaultSorting(defaultTableData: any[], columns: any) {
    return [...defaultTableData].sort((a, b) => {
        const filterColumn = columns.filter((column: { sortByOrder: boolean; }) => column.sortByOrder);

        // Merge all array objects into single object and extract accessor and sortByOrder keys
        let {accessor = "id", sortByOrder = "asc"} = Object.assign(
            {},
            ...filterColumn
        );

        if (a[accessor] === null) return 1;
        if (b[accessor] === null) return -1;
        if (a[accessor] === null && b[accessor] === null) return 0;

        const ascending = a[accessor]
            .toString()
            .localeCompare(b[accessor].toString(), "en", {
                numeric: true,
            });

        return sortByOrder === "asc" ? ascending : -ascending;
    });
}

export const useSortableTable = (data: any, columns: any) => {
    const [tableData, setTableData] = useState(getDefaultSorting(data, columns));
    console.log(tableData);

    const handleSorting = (sortField: any, sortOrder: string) => {
        if (sortField) {
            const sorted = [...tableData].sort((a, b) => {
                if (a[sortField] === null) return 1;
                if (b[sortField] === null) return -1;
                if (a[sortField] === null && b[sortField] === null) return 0;
                return (
                    a[sortField]
                        .toString()
                        .localeCompare(b[sortField].toString(), "en", {
                            numeric: true,
                        }) * (sortOrder === "asc" ? 1 : -1)
                );
            });
            setTableData(sorted);
        }
    };

    return [tableData, handleSorting];
};

我假设数据的类型有一些问题,导致没有元素被排序(并返回一个空数组),但我对React不够熟悉,不知道如何解决这个问题。将欣赏一些指针在哪里看,如何确认(如果它确实是打字)。

csga3l58

csga3l581#

问题在于tableData的状态更新。当它为空时,您正在使用硬件初始化它,并期望tableData在硬件状态更新后将其拾取。但是react不会改变钩子的初始化,更新底层状态的唯一方法是使用状态更新函数(setState)。
为了解决这个问题,我还从排序钩子中公开了set函数。我还删除了额外的状态。
请看这个Sandbox
我用我自己的TableHeader和TableBody组件,因为你没有给。造型留给你。
我还添加了一个组件TestStatePass作为POC。

相关问题