'React-table: How to sort table data based on the changed cell value (override the default sorting with cell props.value)?
Background
I have a table built using react-table with useSortBy hook. Everything works just fine until I change what Cell returns from columns. The thing is, for certain columns I have to modify how data is displayed on the table (without altering the data itself). For example, I have a column on the table that doesnt just display the raw data, it has to combine other values to that data, then display the result. Take a look at the sample code below.
Sample Code
import { useContext, useMemo } from "react";
import "../assets/css/result.css";
import { useTable, useSortBy } from "react-table";
import globalContext from "../globalContext/globalData";
const Result = () => {
const { searchResults } = useContext(globalContext);
const columns = useMemo(() => headers, []); // headers defined below
const data = useMemo(() => searchResults, [searchResults]);
return (
<section id="result">
<div className="title">
<p>Here is my fancy table</p>
</div>
<div className="table">
<Table columns={columns} data={data} />
</div>
</section>
);
};
export default Result;
function Table({ columns, data }) {
const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } = useTable(
{
columns,
data,
},
useSortBy
);
return (
<table {...getTableProps()}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
// Add the sorting props to control sorting. For this example
// we can add them into the header props
<th {...column.getHeaderProps(column.getSortByToggleProps())}>
{column.render("Header")}
{/* Add a sort direction indicator */}
<span>{column.isSorted ? (column.isSortedDesc ? "⇩" : "⇧") : ""}</span>
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{rows.map((row, i) => {
prepareRow(row);
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return (
<td {...cell.getCellProps({ className: cell.column.className })}>
{cell.render("Cell")}
</td>
);
})}
</tr>
);
})}
</tbody>
</table>
);
}
const headers = [
{
Header: "Normal Column",
accessor: "normal_column",
// Cell: props => props.value, // default behaviour
},
{
Header: "Order count",
accessor: "order_count",
Cell: props => `${Number(props.value).toLocaleString("en")} 個`, // 5510 => 5,510 個
// here sorting works fine as the cell display value hasnt changed much
},
{
Header: "Other Column",
accessor: "column_name",
// BUG: sorting does not work properly as it still uses props.value
Cell: props => {
// Here I have to display the value in a different way, combining somethings from the original row data
// displays as expected, but the sorting is still done based on the default props.value under the hood
const { var1, var2, var3 } = props.row.original;
return `${var1}-${var2}-${var3}`; // this should be what sorting is based on, not props.value
},
},
];
Problem
Let's say I change a cell display value from the original 5510 to 5,510 個 (format the number with commas as thousands separators and put space+個 at the end). Sorting works fine with it as sorting results of 5,510 個 and 5510 values do not differ so much.
Here is when it gets tricky: I need a new column that combines two or three row values and outputs a certain display value as shown inside the headers object of the Sample Code. Now the sorting does not work as expected (based on the return value of the Cell).
What I tried
I tried overriding the props.value from Cell function inside my headers object. But it is immutable. So this did not work. How should I go about figuring this out? What am I missing?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
