Unexpected sorting behavior arises due to the implementation in the @tanstack/table-core library
TanStack Table version
8.20.5
Framework/Library version
"react": "^18.2.0",
Describe the bug and the steps to reproduce it
Code Logic: The getAutoSortDir function dynamically determines the initial sort direction based on the type of the first row's value in the column.
-
If it's a string, the sort direction is asc.
-
If it's not a string (e.g., null or number), the sort direction defaults to desc.
Problem: When the first row's value changes due to sorting, the logic re-evaluates, potentially toggling between sort states unpredictably. In your case:
-
Initial value in the first row is not a string → sort starts as desc.
-
After sorting, the first value changes to a string → subsequent toggle resets or disables sorting.
https://github.com/TanStack/table/blob/6b4d616dd7c8917616eb4fecaf09dda7030fd115/packages/table-core/src/features/RowSorting.ts#L335
column.getAutoSortDir = () => {
const firstRow = table.getFilteredRowModel().flatRows[0]
const value = firstRow?.getValue(column.id)
if (typeof value === 'string') {
return 'asc'
}
return 'desc'
}
Your Minimal, Reproducible Example - (Sandbox Highly Recommended)
nda
Screenshots or Videos (Optional)
No response
Do you intend to try to help solve this bug with your own PR?
None
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.
I believe we're running into the same issue when utilizing server-based sorting. We're seeing scenarios where, depending on the column type, the sort will do one of the following.
none→desc→nonenone→asc→none
The expected behavior is one of the following, respectively:
none→desc→asc→nonenone→asc→desc→none
For the time being, it looks like we're able to work around this by specifying a boolean value for sortDescFirst on these columns.
While I plan to set sortDescFirst either at the column level or globally via table.options.sortDescFirst, I wanted to highlight the root cause of the unexpected behavior. This sorting issue might appear in unpredictable scenarios if left unaddressed.
The default sorting direction currently depends on the data type of the first row in the column:
- If the value is a string, sorting defaults to
asc. - Otherwise, it defaults to
desc.
This inconsistency can cause sorting toggles to behave unpredictably, especially in dynamic datasets.
Although sortDescFirst resolves the issue explicitly, it's important to be aware of this behavior, as similar issues might occur in other places where sorting logic is indirectly affected.
Our tables are server rendered and can contain null values so it's possible that the first value is null which causes the table to incorrectly assume the "auto sort direction".
We prefer it to always start from "asc" and decided to overwrite the getAutoSortDir function, because setting sortDescFirst didn't seem to do anything.
Here's an example:
header: ({ column }) => {
column.getAutoSortDir = () => {
return 'asc'
}
}
Also, in some cases we used row.original.for.deep.values (without defining an accessorKey) which causes the firstRow?.getValue(column.id) to return undefined too resulting again in an incorrect auto sort direction.
Related: https://github.com/TanStack/table/issues/5147 https://github.com/TanStack/table/issues/4289 https://github.com/TanStack/table/pull/4698