Sorting

Sort rows by one or more columns. Click a header to cycle through ascending, descending, and unsorted. Hold Shift to add multi-column sorts.

How to Enable

Sorting is enabled by default at the table level (enableSorting: true). Enable it per column:

columnHelper.accessor('name', {
  header: 'Name',
  enableSorting: true,
})

Table Options

OptionTypeDefaultDescription
enableSortingbooleantrueEnable/disable sorting globally
enableMultiSortbooleantrueAllow sorting by multiple columns
enableSortingRemovalbooleantrueAllow removing sort (third click)
maxMultiSortColCountnumberInfinityMax simultaneous sort columns
manualSortingbooleanfalseIf true, sorting is handled externally (server-side)
sortDescFirstbooleanfalseStart with descending on first click
isMultiSortEvent(e) => booleanShift keyWhich modifier key triggers multi-sort
onSortingChangeOnChangeFn<SortingState>--Callback when sorting state changes
postSortRows(rows) => Row[] | void--Reorder the final sorted rows before render (AG-parity)

Column Options

OptionTypeDefaultDescription
enableSortingbooleantrueEnable sorting for this column
sortingFnSortingFnOption'auto'Sort function name or custom function
sortDescFirstbooleanfalseStart descending for this column
invertSortingbooleanfalseInvert sort direction
sortUndefinedfalse | -1 | 1 | 'first' | 'last'--Where to place undefined values

Built-in Sorting Functions

NameDescription
alphanumericNatural sort -- "item2" before "item10" (case-insensitive)
alphanumericCaseSensitiveNatural sort (case-sensitive)
textLocale-aware string comparison (case-insensitive)
textCaseSensitiveLocale-aware string comparison (case-sensitive)
datetimeSorts Date objects and date strings by timestamp
basicSimple > / < comparison for numbers and strings

Custom Sort Function

columnHelper.accessor('priority', {
  header: 'Priority',
  sortingFn: (rowA, rowB, columnId) => {
    const order = { high: 3, medium: 2, low: 1 }
    const a = order[rowA.getValue<string>(columnId)] ?? 0
    const b = order[rowB.getValue<string>(columnId)] ?? 0
    return a - b
  },
})

Post-sort hook

postSortRows runs after the sorted row model is built and lets you reorder the final rows before render — the AG Grid postSortRows equivalent. Return a new array or mutate the given one in place. It runs on every sort (and with no active sort), so it is the right place to keep child rows under their parents:

const table = useTable({
  data,
  columns,
  postSortRows: (rows) => {
    const pinned = rows.filter((r) => r.original.pinned)
    const rest = rows.filter((r) => !r.original.pinned)
    return [...pinned, ...rest]
  },
})

postSortRows is skipped under manualSorting.

Programmatic Control

// Set sorting
table.setSorting([{ id: 'name', desc: false }])

// Add a sort column
table.setSorting((prev) => [...prev, { id: 'age', desc: true }])

// Reset to no sorting
table.resetSorting(true)

// Toggle sort on a specific column
table.getColumn('name')?.toggleSorting()

// Check if a column is sorted
const direction = table.getColumn('name')?.getIsSorted() // 'asc' | 'desc' | false