table icon indicating copy to clipboard operation
table copied to clipboard

Sorting direction not updating properly with manual sorting and same values on current page

Open jenmak-tangelo opened this issue 1 year ago • 8 comments

Describe the bug

When the data in the table column is all the same value (an empty string), the header.column.getIsSorted() function goes from ascending to false and never reaches descending.

Your minimal, reproducible example

Do not have

Steps to reproduce

Sort by a column with data that has empty values. See that the empty values are shown first with ascending sorting. Try to click again (execute header.column.getToggleSortingHandler()) And see that the sorting direction changes from ascending to false.

Expected behavior

The sorting direction should be changing to descending, instead of returning to false.

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

macOS

react-table version

8.10.3

TypeScript version

5.1.6

Additional context

No response

Terms & Code of Conduct

  • [X] I agree to follow this project's Code of Conduct
  • [X] I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.

jenmak-tangelo avatar Oct 30 '23 13:10 jenmak-tangelo

I have the same problem.

  1. I call column.toggleSorting()
  2. column.getAutoSortDir() returns asc because the first value is a string, so the column will be sorted asc initially.

https://github.com/TanStack/table/blob/a1e9732e6fc3446a2ae80db72a1f2b46a5c11e46/packages/table-core/src/features/Sorting.ts#L332-L342

  1. I fetch the sorted data to the table from the API and the first value of the column is now null instead of a string.
  2. I call column.toggleSorting() again
  3. column.getAutoSortDir() now returns desc instead of asc because the first value is null
  4. That's why column.getNextSortingOrder() decides to turn off sorting for the column by returning false because it thinks it had already been ordered desc previously

My current workaround is to set the sortDescFirst: true manually for the column (or globally for the table), so the getAutoSortDir() won't be used.

https://github.com/TanStack/table/blob/a1e9732e6fc3446a2ae80db72a1f2b46a5c11e46/packages/table-core/src/features/Sorting.ts#L68-L73

zsilbi avatar Nov 13 '23 11:11 zsilbi

Same issue, thanks @zsilbi, we use your trick as a temp workaround.

Any updates to have a proper way to have ASC first without breaking the lib ?

tomdubraw avatar Dec 11 '23 14:12 tomdubraw

I also encountered this problem when implementing manual sorting. After some time of debugging I found the problem. This is caused by comparing the value of a column with a string, which leads to a change in the default auto sort direction value, when value was a string during the first sort and null or undefined during the second.

Screenshot 2024-01-15 at 12 57 43

Maybe you should define a default auto sort direction based only on sortDescFirst?

Oberin98 avatar Jan 15 '24 12:01 Oberin98

May be this example will be helpful to someone Screenshot 2024-01-15 at 16 56 48

Oberin98 avatar Jan 15 '24 15:01 Oberin98

@Oberin98 I tried use your snippet above, but it doesn't remove my sorting, the "asc->desc" flow goes right but i can remove the sorting.

const handleSorting = () => { const isSortable = column.getCanSort(); if (isSortable) { const ctx = header.getContext(); const isSorted = header.column.getIsSorted(); const isSortDescFirst = !!header.column.columnDef.sortDescFirst || !!ctx.table.options.sortDescFirst; const isEnableSortingRemoval = !!ctx.table.options.enableSortingRemoval; if (!isSorted) { header.column.toggleSorting(isSortDescFirst); } if (isSorted === "asc") { if (isSortDescFirst && isEnableSortingRemoval) { header.column.clearSorting(); } else { header.column.toggleSorting(true); } } if (isSorted === "desc") { if (!isSortDescFirst && isEnableSortingRemoval) { header.column.clearSorting(); } else { header.column.toggleSorting(false); } } } };

And my usage:

<div {...{ className: header.column.getCanSort() ? "cursor-pointer select-none " : "bg-slate-50", onClick: handleSorting, }} > {flexRender(header.column.columnDef.header, header.getContext())} {{ asc: "🔼", desc: "🔽", false: "", }[header.column.getIsSorted()] ?? null} </div>

eliranma avatar Mar 17 '24 09:03 eliranma

@eliranma did you set enableSortingRemoval option to true?

Oberin98 avatar Mar 18 '24 12:03 Oberin98

@Oberin98 Yap, // Sorting enableSorting: true, onSortingChange: handleSorting, enableSortingRemoval: true, enableMultiRemove: true, sortDescFirst: true, manualSorting: true,

eliranma avatar Mar 20 '24 11:03 eliranma

Hi Guys, any suggestion? maybe downgrade to previous version?

eliranma avatar Mar 26 '24 07:03 eliranma