我正在构建我的第一个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不够熟悉,不知道如何解决这个问题。将欣赏一些指针在哪里看,如何确认(如果它确实是打字)。
1条答案
按热度按时间csga3l581#
问题在于tableData的状态更新。当它为空时,您正在使用硬件初始化它,并期望tableData在硬件状态更新后将其拾取。但是react不会改变钩子的初始化,更新底层状态的唯一方法是使用状态更新函数(setState)。
为了解决这个问题,我还从排序钩子中公开了set函数。我还删除了额外的状态。
请看这个Sandbox
我用我自己的TableHeader和TableBody组件,因为你没有给。造型留给你。
我还添加了一个组件TestStatePass作为POC。