我正在开发一个使用类的 React 应用程序,它还使用 React-table v6.8.6 在页面上呈现一些数据。我希望能够自定义列标题上可用的排序功能以满足我的用户体验要求,但我不知道如何开始!
这是一个示例 github 存储库,我在其中构建了我的情况的简化版本,并使用虚假数据,如果您想在本地运行它,这有助于可视化问题。
在示例存储库中,这是 package.json:
{
"name": "react-table-v6",
"version": "0.1.0",
"private": true,
"dependencies": {
"autoprefixer": "^10.4.19",
"moment": "^2.29.4",
"postcss": "^8.4.38",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"react-scripts": "^5.0.1",
"react-table": "^6.8.6",
"tailwindcss": "^3.4.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
这是我的应用程序在index.js 文件中的内容,其中我的表格是:
import React from "react";
import { render } from "react-dom";
import {
makeData,
Tips,
datetimeTinyFormatterUTC,
sortDatetimes,
} from "./Utils";
import './index.css';
import ReactTable from "react-table";
import "react-table/react-table.css";
class App extends React.Component {
constructor() {
super();
this.state = {
data: makeData(),
};
}
render() {
const { data } = this.state;
return (
<div>
<ReactTable
data={data}
columns={[
{
Header: "Date",
id: "arrivalDatetime",
accessor: (item) => (
datetimeTinyFormatterUTC(item.arrivalDatetime)
),
minWidth: 100,
maxWidth: 200,
Cell: props => <div>{props.value}</div>,
sortMethod: (a, b) => sortDatetimes(a, b)
},
{
Header: "Destination",
id: "destination",
//here I might get the origin and destination strings as 'UNKNOWN', which would make all strings the same in all rows
accessor: flight => flight.origin + ' > ' + flight.destination,
Cell: props => <div>{props.value}</div>,
minWidth: 100,
maxWidth: 200,
},
{
id: "savings",
Header: "Savings",
accessor: trip => {
const saved = trip.test.reduce((total, b) => {
if(b.succeeded && b.saved > 0) {total += b.saved}
return total;
}, 0);
return saved;
},
minWidth: 100,
maxWidth: 200,
Cell: props => <div>{props.value} dollars</div>
},
{
Header: "success",
id: "success",
accessor: item => {
const succeeded = item.succeededCount;
const total = item.overall;
return { succeeded, total };
},
minWidth: 100,
maxWidth: 200,
Cell: item => <div>{item.value.succeeded + ' / ' + item.value.total}</div>,
sortMethod: (a, b) => a.succeeded > b.succeeded ? 1 : -1
},
{
id: "projected-savings",
Header: "Max Savings",
accessor: () => {
// here I have more logic here which might lead me to get a 0 in all rows
const saved = 0;
return saved;
},
minWidth: 100,
maxWidth: 200,
Cell: props => <div>{props.value} dollars</div>
},
]}
defaultSorted={[
{
id: 'arrivalDatetime',
desc: false
}
]}
sortable={true}
defaultPageSize={10}
className="-striped -highlight"
/>
<br />
<Tips />
</div>
);
}
}
render(<App />, document.getElementById("root"));
这是 utils.js 文件,其中包含有助于创建和格式化数据的 utils 函数:
import React from "react";
import moment from "moment";
import "./index.css";
const range = (len) => {
const arr = [];
for (let i = 0; i < len; i++) {
arr.push(i);
}
return arr;
};
const getRamdomDateInBetween = (start, end) => {
start = Date.parse(start);
end = Date.parse(end);
return new Date(Math.floor(Math.random() * (end - start + 1) + start));
};
const newRow = () => {
return {
arrivalDatetime: getRamdomDateInBetween("2023-01-01", "2023-02-28"),
test: [{
succeeded: true,
saved: Math.floor(Math.random() * 1500),
}, {
succeeded: true,
saved: Math.floor(Math.random() * 100),
}, {
succeeded: true,
saved: Math.floor(Math.random() * 300),
}, {
succeeded: false,
saved: Math.floor(Math.random() * 1000),
}
],
origin: "XXX",
destination: "YYY",
durationInMinutes: Math.floor(Math.random() * 100),
id: "822e7a0f-10f7-4de1-bdc4",
savings: 1798,
succeededCount: Math.floor(Math.random() * 4),
overall: 4,
};
};
export function makeData(len = 12) {
return range(len).map((d) => {
return {
...newRow(),
};
});
}
export const datetimeTinyFormatterUTC = (dateTimeUnix) => {
return moment.utc(dateTimeUnix).format("MMM DD, HH:mm");
};
export const sortDatetimes = (a, b) => {
if (moment(a, "MMM DD, hh:mm a").isBefore(moment(b, "MMM DD, hh:mm a"))) {
return 1;
}
return -1;
};
export const Tips = () => (
<div style={{ textAlign: "center" }}>
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
);
index.css 文件中还没有任何相关内容。
我有一个包含几列的表:日期、目的地、储蓄、成功和最大储蓄,在每一列中,我要么处理数据以以某种格式显示它,要么处理对象中的 2 个字段以获取一些新值/组合值,然后我对结果进行自定义显示。
当我得到一整列,所有行中的数据都相同,例如所有行中的数字相同(请参阅“最大节省”列)或相同的字符串(请参阅“目标”列)时,单击标题只会将原始数据的顺序翻转回来并向前,这似乎有点毫无意义,如果用户在这些情况下无法对该列进行排序,我的用户体验团队会更喜欢。我不知道如何在这种情况下启用单击标题/排序。
我需要一个 sortMethod 吗?实现这一目标会是什么样子?或者我如何删除特定列标题上的点击功能?或者还有其他我想不到的方法吗?
注意,如果您访问我的 github 存储库,我已在自述文件中复制了 tanstack v6 存储库 中的所有 React-table v6 信息,以便您可以在任一位置检查它。
在尝试了一段时间之后,我实际上已经成功地找到了一些可以让我做到这一点的东西。
我在相关列上添加了可排序属性,并使其以通过检查数据数组获得的布尔值为条件。 这意味着我在渲染的开头添加以下内容:
const { data } = this.state;
const noOrigin = data.every((item)=> item.origin === "XXX" )
const noSavings = data.every((item)=> item.savings === data[0].savings)
在可排序字段的列定义中:
{
Header: "Destination",
id: "destination",
//here I might get the origin and destination strings as 'UNKNOWN', which would make all strings the same in all rows
accessor: flight => flight.origin + ' > ' + flight.destination,
Cell: props => <div>{props.value}</div>,
minWidth: 100,
maxWidth: 200,
sortable: !!noOrigin ? false : true
},
我没有太多数据需要处理,我认为我的数组中的项目不会超过一百个,所以这可能还不错。但如果有人有更好的建议,我很乐意看到:)