'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