最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - react-table sorting not working for column with custom cell - Stack Overflow

programmeradmin2浏览0评论

I am using the react-table plugin and am having difficulty getting the sorting to work for one column that has a custom link defined.

This column's content is based on some properties from the data in that row so I have created a custom Cell for it. It displays OK, but the sorting performs very strangely.

I am pretty sure the issue is in the columns definition but I will post all the code here for pleteness:

export default function CloudfrontList() {
    const [loading, setLoading] = useState(true);
    const [columns, setColumns] = useState([]);
    const [data, setData] = useState([]);

    const getDataForTable = async () => {
        const _columns = [{
            // This is the cell that doesn't sort properly
            Header: "Name",
            Cell: cell => {
                const row = cell.row.original;
                const value = rowment ? rowment : row.origins[0].domain_name;
                return (
                    <Link href="/view/cloudfront/[id]" as={`/view/cloudfront/${row.id}`}>
                        <a>{value}</a>
                    </Link>
                );
            },
            accessor: row => {
                return rowment ? rowment : row.origins[0].domain_name;
            },
            id: Math.random() // It needs a unique ID, right?
        }, {
            Header: "Identifier",
            accessor: "id"
        }, {
            Header: "Product",
            accessor: "tags.Product"
        }];

        const _assets = await readAllAssetsOfType(AssetType.Cloudfront);

        setColumns(_columns);
        setData(_assets);
        setLoading(false);
    };

    useEffect(() => {
        getDataForTable();
    }, []);

    return (
        <>
            <Head>
                <title>Cloudfront List :: {siteTitle}</title>
            </Head>

            {loading ? (
                "loading..."
            ) : (
                <Card>
                    <CardHeader>
                        All Cloudfront Assets
                        <Badge color="secondary" className="ml-2">{data.length}</Badge>
                    </CardHeader>
                    <CardBody>
                        <Table columns={columns} data={data} />
                    </CardBody>
                </Card>
            )}
        </>
    );
}


function Table({ columns, data }) {
    const {
        getTableProps,
        getTableBodyProps,
        headerGroups,
        rows,
        prepareRow,
    } = useTable(
        {
            columns,
            data
        },
        useSortBy
    );

    return (
        <>
            <table {...getTableProps()} className="table table-sm table-hover">
                <thead>
                    {headerGroups.map(headerGroup => (
                        <tr {...headerGroup.getHeaderGroupProps()}>
                            {headerGroup.headers.map(column => (
                                <th {...column.getHeaderProps(column.getSortByToggleProps())}>
                                    {column.render("Header")}
                                    <span>
                                        {column.isSorted
                                            ? column.isSortedDesc
                                                ? <FontAwesomeIcon icon={faSortDown} style={{ color: "#969696", width: "0.5rem" }} />
                                                : <FontAwesomeIcon icon={faSortUp} style={{ color: "#969696", width: "0.5rem" }} />
                                            : (
                                                <FontAwesomeIcon icon={faSort} style={{ color: "#969696", width: "0.5rem" }} />
                                            )}
                                    </span>
                                </th>
                            ))}
                        </tr>
                    ))}
                </thead>
                <tbody {...getTableBodyProps()}>
                    {rows.map(
                        row => {
                            prepareRow(row);
                            return (
                                <tr {...row.getRowProps()}>
                                    {row.cells.map(cell => {
                                        return (
                                            <td {...cell.getCellProps()}>{cell.render("Cell")}</td>
                                        );
                                    })}
                                </tr>
                            );
                        }
                    )}
                </tbody>
            </table>
        </>
    );
}

Here's an example of what happens when I click the Name header; it does sort but it seems to divide the rows into two groups:

I thought maybe the issue was the link definition - that it may have been sorting the tag - but when I change it to:

Cell: cell => {
   const row = cell.row.original;
   const value = rowment ? rowment : row.origins[0].domain_name;
   return (
      value
   );
},

...the issue persists. Can someone point out where I am going wrong?

I am using the react-table plugin and am having difficulty getting the sorting to work for one column that has a custom link defined.

This column's content is based on some properties from the data in that row so I have created a custom Cell for it. It displays OK, but the sorting performs very strangely.

I am pretty sure the issue is in the columns definition but I will post all the code here for pleteness:

export default function CloudfrontList() {
    const [loading, setLoading] = useState(true);
    const [columns, setColumns] = useState([]);
    const [data, setData] = useState([]);

    const getDataForTable = async () => {
        const _columns = [{
            // This is the cell that doesn't sort properly
            Header: "Name",
            Cell: cell => {
                const row = cell.row.original;
                const value = row.ment ? row.ment : row.origins[0].domain_name;
                return (
                    <Link href="/view/cloudfront/[id]" as={`/view/cloudfront/${row.id}`}>
                        <a>{value}</a>
                    </Link>
                );
            },
            accessor: row => {
                return row.ment ? row.ment : row.origins[0].domain_name;
            },
            id: Math.random() // It needs a unique ID, right?
        }, {
            Header: "Identifier",
            accessor: "id"
        }, {
            Header: "Product",
            accessor: "tags.Product"
        }];

        const _assets = await readAllAssetsOfType(AssetType.Cloudfront);

        setColumns(_columns);
        setData(_assets);
        setLoading(false);
    };

    useEffect(() => {
        getDataForTable();
    }, []);

    return (
        <>
            <Head>
                <title>Cloudfront List :: {siteTitle}</title>
            </Head>

            {loading ? (
                "loading..."
            ) : (
                <Card>
                    <CardHeader>
                        All Cloudfront Assets
                        <Badge color="secondary" className="ml-2">{data.length}</Badge>
                    </CardHeader>
                    <CardBody>
                        <Table columns={columns} data={data} />
                    </CardBody>
                </Card>
            )}
        </>
    );
}


function Table({ columns, data }) {
    const {
        getTableProps,
        getTableBodyProps,
        headerGroups,
        rows,
        prepareRow,
    } = useTable(
        {
            columns,
            data
        },
        useSortBy
    );

    return (
        <>
            <table {...getTableProps()} className="table table-sm table-hover">
                <thead>
                    {headerGroups.map(headerGroup => (
                        <tr {...headerGroup.getHeaderGroupProps()}>
                            {headerGroup.headers.map(column => (
                                <th {...column.getHeaderProps(column.getSortByToggleProps())}>
                                    {column.render("Header")}
                                    <span>
                                        {column.isSorted
                                            ? column.isSortedDesc
                                                ? <FontAwesomeIcon icon={faSortDown} style={{ color: "#969696", width: "0.5rem" }} />
                                                : <FontAwesomeIcon icon={faSortUp} style={{ color: "#969696", width: "0.5rem" }} />
                                            : (
                                                <FontAwesomeIcon icon={faSort} style={{ color: "#969696", width: "0.5rem" }} />
                                            )}
                                    </span>
                                </th>
                            ))}
                        </tr>
                    ))}
                </thead>
                <tbody {...getTableBodyProps()}>
                    {rows.map(
                        row => {
                            prepareRow(row);
                            return (
                                <tr {...row.getRowProps()}>
                                    {row.cells.map(cell => {
                                        return (
                                            <td {...cell.getCellProps()}>{cell.render("Cell")}</td>
                                        );
                                    })}
                                </tr>
                            );
                        }
                    )}
                </tbody>
            </table>
        </>
    );
}

Here's an example of what happens when I click the Name header; it does sort but it seems to divide the rows into two groups:

I thought maybe the issue was the link definition - that it may have been sorting the tag - but when I change it to:

Cell: cell => {
   const row = cell.row.original;
   const value = row.ment ? row.ment : row.origins[0].domain_name;
   return (
      value
   );
},

...the issue persists. Can someone point out where I am going wrong?

Share Improve this question asked Aug 3, 2020 at 10:18 MSOACCMSOACC 3,6852 gold badges34 silver badges51 bronze badges 2
  • You might need to define the sort method by yourself using sortMethod. Like in this example: codesandbox.io/s/l776y47n9?file=/index.js – Mosh Feu Commented Aug 3, 2020 at 13:08
  • btw, the "unique id" is for each column, you can just have something like id: "name", no need to generate unique strings. – Szaman Commented Jun 11, 2021 at 15:36
Add a ment  | 

2 Answers 2

Reset to default 3

It worked for me leaving the accessor property in the column empty:

const columns: Column[] = [
  {
    Header: 'Name',
    Cell: (data: Cell) => {
      const original: any = data.row.original;

      return 'Something';
    },
    accessor: '',
  }
]

This appears fine to me, if you see in snapshot, first sorted set has upppercase first letter and second set has lowercase letters, means the default sorting seems to case-sensitive.

You will be required to use custom sorting or any other sorting method(if available) to do case insensitive sorting.

发布评论

评论列表(0)

  1. 暂无评论