框架
版本
企业版

排序指南

示例

想跳过实现步骤?查看这些示例

API

排序 API

排序指南

TanStack Table 为您可能遇到的几乎任何排序用例提供了解决方案。本指南将引导您了解各种选项,您可以使用这些选项来自定义内置的客户端排序功能,以及如何选择退出客户端排序,转而使用手动服务端排序。

排序状态

排序状态被定义为一个对象数组,具有以下形状

tsx
type ColumnSort = {
  id: string
  desc: boolean
}
type SortingState = ColumnSort[]
type ColumnSort = {
  id: string
  desc: boolean
}
type SortingState = ColumnSort[]

由于排序状态是一个数组,因此可以一次按多列排序。请阅读下文以了解有关多列排序自定义的更多信息。

访问排序状态

您可以像访问任何其他状态一样,直接从表格实例访问排序状态,使用 table.getState() API。

tsx
const table = useReactTable({
  columns,
  data,
  //...
})

console.log(table.getState().sorting) // access the sorting state from the table instance
const table = useReactTable({
  columns,
  data,
  //...
})

console.log(table.getState().sorting) // access the sorting state from the table instance

但是,如果您需要在表格初始化之前访问排序状态,您可以像下面这样“控制”排序状态。

受控排序状态

如果您需要轻松访问排序状态,您可以使用 state.sortingonSortingChange 表格选项在您自己的状态管理中控制/管理排序状态。

tsx
const [sorting, setSorting] = useState<SortingState>([]) // can set initial sorting state here
//...
// use sorting state to fetch data from your server or something...
//...
const table = useReactTable({
  columns,
  data,
  //...
  state: {
    sorting,
  },
  onSortingChange: setSorting,
})
const [sorting, setSorting] = useState<SortingState>([]) // can set initial sorting state here
//...
// use sorting state to fetch data from your server or something...
//...
const table = useReactTable({
  columns,
  data,
  //...
  state: {
    sorting,
  },
  onSortingChange: setSorting,
})

初始排序状态

如果您不需要在您自己的状态管理或作用域中控制排序状态,但您仍然想要设置初始排序状态,您可以使用 initialState 表格选项代替 state

jsx
const table = useReactTable({
  columns,
  data,
  //...
  initialState: {
    sorting: [
      {
        id: 'name',
        desc: true, // sort by name in descending order by default
      },
    ],
  },
})
const table = useReactTable({
  columns,
  data,
  //...
  initialState: {
    sorting: [
      {
        id: 'name',
        desc: true, // sort by name in descending order by default
      },
    ],
  },
})

注意:不要同时使用 initialState.sortingstate.sorting,因为 state.sorting 中的初始化状态将覆盖 initialState.sorting

客户端排序 vs 服务端排序

您应该使用客户端排序还是服务端排序完全取决于您是否同时使用客户端或服务端分页或筛选。请保持一致,因为将客户端排序与服务端分页或筛选一起使用只会对当前加载的数据进行排序,而不会对整个数据集进行排序。

手动服务端排序

如果您计划仅在您的后端逻辑中使用您自己的服务端排序,则无需提供排序后的行模型。但是,如果您已经提供了排序行模型,但想要禁用它,您可以使用 manualSorting 表格选项。

jsx
const [sorting, setSorting] = useState<SortingState>([])
//...
const table = useReactTable({
  columns,
  data,
  getCoreRowModel: getCoreRowModel(),
  //getSortedRowModel: getSortedRowModel(), //not needed for manual sorting
  manualSorting: true, //use pre-sorted row model instead of sorted row model
  state: {
    sorting,
  },
  onSortingChange: setSorting,
})
const [sorting, setSorting] = useState<SortingState>([])
//...
const table = useReactTable({
  columns,
  data,
  getCoreRowModel: getCoreRowModel(),
  //getSortedRowModel: getSortedRowModel(), //not needed for manual sorting
  manualSorting: true, //use pre-sorted row model instead of sorted row model
  state: {
    sorting,
  },
  onSortingChange: setSorting,
})

注意:当 manualSorting 设置为 true 时,表格将假定您提供的数据已排序,并且不会对其应用任何排序。

客户端排序

要实现客户端排序,首先您必须为表格提供一个排序行模型。您可以从 TanStack Table 导入 getSortedRowModel 函数,它将用于将您的行转换为排序后的行。

jsx
import { useReactTable } from '@tanstack/react-table'
//...
const table = useReactTable({
  columns,
  data,
  getCoreRowModel: getCoreRowModel(),
  getSortedRowModel: getSortedRowModel(), //provide a sorting row model
})
import { useReactTable } from '@tanstack/react-table'
//...
const table = useReactTable({
  columns,
  data,
  getCoreRowModel: getCoreRowModel(),
  getSortedRowModel: getSortedRowModel(), //provide a sorting row model
})

排序函数

所有列的默认排序函数是从列的数据类型推断出来的。但是,为特定列定义您想要使用的确切排序函数可能很有用,特别是如果您的任何数据是可为空的或不是标准数据类型。

您可以使用 sortingFn 列选项在每列的基础上确定自定义排序函数。

默认情况下,有 6 个内置排序函数可供选择

  • alphanumeric - 按混合字母数字值排序,不区分大小写。速度较慢,但如果您的字符串包含需要自然排序的数字,则更准确。
  • alphanumericCaseSensitive - 按混合字母数字值排序,区分大小写。速度较慢,但如果您的字符串包含需要自然排序的数字,则更准确。
  • text - 按文本/字符串值排序,不区分大小写。速度更快,但如果您的字符串包含需要自然排序的数字,则不太准确。
  • textCaseSensitive - 按文本/字符串值排序,区分大小写。速度更快,但如果您的字符串包含需要自然排序的数字,则不太准确。
  • datetime - 按时间排序,如果您的值是 Date 对象,请使用此函数。
  • basic - 使用基本的/标准的 a > b ? 1 : a < b ? -1 : 0 比较进行排序。这是最快的排序函数,但可能不是最准确的。

您还可以定义自己的自定义排序函数,可以作为 sortingFn 列选项,也可以使用 sortingFns 表格选项作为全局排序函数。

自定义排序函数

当在 sortingFns 表格选项或 sortingFn 列选项中定义自定义排序函数时,它应该具有以下签名

tsx
//optionally use the SortingFn to infer the parameter types
const myCustomSortingFn: SortingFn<TData> = (rowA: Row<TData>, rowB: Row<TData>, columnId: string) => {
  return //-1, 0, or 1 - access any row data using rowA.original and rowB.original
}
//optionally use the SortingFn to infer the parameter types
const myCustomSortingFn: SortingFn<TData> = (rowA: Row<TData>, rowB: Row<TData>, columnId: string) => {
  return //-1, 0, or 1 - access any row data using rowA.original and rowB.original
}

注意:比较函数不需要考虑列是否按降序或升序排列。行模型将处理该逻辑。sortingFn 函数只需要提供一致的比较。

每个排序函数接收 2 行和一个列 ID,并期望使用列 ID 比较这两行,以升序返回 -101。这是一个速查表

返回升序
-1a < b
0a === b
1a > b
jsx
const columns = [
  {
    header: () => 'Name',
    accessorKey: 'name',
    sortingFn: 'alphanumeric', // use built-in sorting function by name
  },
  {
    header: () => 'Age',
    accessorKey: 'age',
    sortingFn: 'myCustomSortingFn', // use custom global sorting function
  },
  {
    header: () => 'Birthday',
    accessorKey: 'birthday',
    sortingFn: 'datetime', // recommended for date columns
  },
  {
    header: () => 'Profile',
    accessorKey: 'profile',
    // use custom sorting function directly
    sortingFn: (rowA, rowB, columnId) => {
      return rowA.original.someProperty - rowB.original.someProperty
    },
  }
]
//...
const table = useReactTable({
  columns,
  data,
  getCoreRowModel: getCoreRowModel(),
  getSortedRowModel: getSortedRowModel(),
  sortingFns: { //add a custom sorting function
    myCustomSortingFn: (rowA, rowB, columnId) => {
      return rowA.original[columnId] > rowB.original[columnId] ? 1 : rowA.original[columnId] < rowB.original[columnId] ? -1 : 0
    },
  },
})
const columns = [
  {
    header: () => 'Name',
    accessorKey: 'name',
    sortingFn: 'alphanumeric', // use built-in sorting function by name
  },
  {
    header: () => 'Age',
    accessorKey: 'age',
    sortingFn: 'myCustomSortingFn', // use custom global sorting function
  },
  {
    header: () => 'Birthday',
    accessorKey: 'birthday',
    sortingFn: 'datetime', // recommended for date columns
  },
  {
    header: () => 'Profile',
    accessorKey: 'profile',
    // use custom sorting function directly
    sortingFn: (rowA, rowB, columnId) => {
      return rowA.original.someProperty - rowB.original.someProperty
    },
  }
]
//...
const table = useReactTable({
  columns,
  data,
  getCoreRowModel: getCoreRowModel(),
  getSortedRowModel: getSortedRowModel(),
  sortingFns: { //add a custom sorting function
    myCustomSortingFn: (rowA, rowB, columnId) => {
      return rowA.original[columnId] > rowB.original[columnId] ? 1 : rowA.original[columnId] < rowB.original[columnId] ? -1 : 0
    },
  },
})

自定义排序

有很多表格和列选项可供您使用,以进一步自定义排序 UX 和行为。

禁用排序

您可以使用 enableSorting 列选项或表格选项禁用特定列或整个表格的排序。

jsx
const columns = [
  {
    header: () => 'ID',
    accessorKey: 'id',
    enableSorting: false, // disable sorting for this column
  },
  {
    header: () => 'Name',
    accessorKey: 'name',
  },
  //...
]
//...
const table = useReactTable({
  columns,
  data,
  enableSorting: false, // disable sorting for the entire table
})
const columns = [
  {
    header: () => 'ID',
    accessorKey: 'id',
    enableSorting: false, // disable sorting for this column
  },
  {
    header: () => 'Name',
    accessorKey: 'name',
  },
  //...
]
//...
const table = useReactTable({
  columns,
  data,
  enableSorting: false, // disable sorting for the entire table
})

排序方向

默认情况下,使用 toggleSorting API 循环列排序时,字符串列的第一个排序方向是升序,数字列的第一个排序方向是降序。您可以使用 sortDescFirst 列选项或表格选项更改此行为。

jsx
const columns = [
  {
    header: () => 'Name',
    accessorKey: 'name',
    sortDescFirst: true, //sort by name in descending order first (default is ascending for string columns)
  },
  {
    header: () => 'Age',
    accessorKey: 'age',
    sortDescFirst: false, //sort by age in ascending order first (default is descending for number columns)
  },
  //...
]
//...
const table = useReactTable({
  columns,
  data,
  sortDescFirst: true, //sort by all columns in descending order first (default is ascending for string columns and descending for number columns)
})
const columns = [
  {
    header: () => 'Name',
    accessorKey: 'name',
    sortDescFirst: true, //sort by name in descending order first (default is ascending for string columns)
  },
  {
    header: () => 'Age',
    accessorKey: 'age',
    sortDescFirst: false, //sort by age in ascending order first (default is descending for number columns)
  },
  //...
]
//...
const table = useReactTable({
  columns,
  data,
  sortDescFirst: true, //sort by all columns in descending order first (default is ascending for string columns and descending for number columns)
})

注意:您可能需要在任何具有可为空值的列上显式设置 sortDescFirst 列选项。如果列包含可为空的值,则表格可能无法正确确定列是数字还是字符串。

反转排序

反转排序与更改默认排序方向不同。如果列的 invertSorting 列选项为 true,则“desc/asc”排序状态仍将像往常一样循环,但行的实际排序将被反转。这对于具有反向最佳/最差比例的值很有用,其中较低的数字更好,例如排名(第 1 名、第 2 名、第 3 名)或类似高尔夫的计分。

jsx
const columns = [
  {
    header: () => 'Rank',
    accessorKey: 'rank',
    invertSorting: true, // invert the sorting for this column. 1st -> 2nd -> 3rd -> ... even if "desc" sorting is applied
  },
  //...
]
const columns = [
  {
    header: () => 'Rank',
    accessorKey: 'rank',
    invertSorting: true, // invert the sorting for this column. 1st -> 2nd -> 3rd -> ... even if "desc" sorting is applied
  },
  //...
]

排序未定义值

任何未定义的值都将根据 sortUndefined 列选项或表格选项排序到列表的开头或结尾。您可以为您的特定用例自定义此行为。

如果未指定,sortUndefined 的默认值为 1,未定义的值将以较低的优先级排序(降序),如果升序,未定义的值将出现在列表的末尾。

  • 'first' - 未定义的值将被推到列表的开头
  • 'last' - 未定义的值将被推到列表的末尾
  • false - 未定义的值将被视为并列,需要按下一个列筛选器或原始索引排序(以适用者为准)
  • -1 - 未定义的值将以较高的优先级排序(升序)(如果升序,未定义的值将出现在列表的开头)
  • 1 - 未定义的值将以较低的优先级排序(降序)(如果升序,未定义的值将出现在列表的末尾)

注意:'first''last' 选项是 v8.16.0 中的新功能

jsx
const columns = [
  {
    header: () => 'Rank',
    accessorKey: 'rank',
    sortUndefined: -1, // 'first' | 'last' | 1 | -1 | false
  },
]
const columns = [
  {
    header: () => 'Rank',
    accessorKey: 'rank',
    sortUndefined: -1, // 'first' | 'last' | 1 | -1 | false
  },
]

移除排序

默认情况下,在循环列的排序状态时,移除排序的功能已启用。您可以使用 enableSortingRemoval 表格选项禁用此行为。如果您想确保始终至少对一列进行排序,则此行为很有用。

当使用 getToggleSortingHandlertoggleSorting API 时,默认行为是像这样循环排序状态

'none' -> 'desc' -> 'asc' -> 'none' -> 'desc' -> 'asc' -> ...

如果您禁用移除排序,则行为将如下所示

'none' -> 'desc' -> 'asc' -> 'desc' -> 'asc' -> ...

一旦列被排序且 enableSortingRemovalfalse,则在该列上切换排序将永远不会移除排序。但是,如果用户按另一列排序,并且它不是多列排序事件,则排序将从前一列中移除,并仅应用于新列。

如果您想确保始终至少对一列进行排序,请将 enableSortingRemoval 设置为 false

jsx
const table = useReactTable({
  columns,
  data,
  enableSortingRemoval: false, // disable the ability to remove sorting on columns (always none -> asc -> desc -> asc)
})
const table = useReactTable({
  columns,
  data,
  enableSortingRemoval: false, // disable the ability to remove sorting on columns (always none -> asc -> desc -> asc)
})

多列排序

如果使用 column.getToggleSortingHandler API,则默认启用一次按多列排序。如果用户在单击列标题时按住 Shift 键,则表格将按该列以及已排序的列进行排序。如果您使用 column.toggleSorting API,则必须手动传入是否使用多列排序。(column.toggleSorting(desc, multi))。

禁用多列排序

您可以使用 enableMultiSort 列选项或表格选项禁用特定列或整个表格的多列排序。禁用特定列的多列排序会将所有现有排序替换为新列的排序。

jsx
const columns = [
  {
    header: () => 'Created At',
    accessorKey: 'createdAt',
    enableMultiSort: false, // always sort by just this column if sorting by this column
  },
  //...
]
//...
const table = useReactTable({
  columns,
  data,
  enableMultiSort: false, // disable multi-sorting for the entire table
})
const columns = [
  {
    header: () => 'Created At',
    accessorKey: 'createdAt',
    enableMultiSort: false, // always sort by just this column if sorting by this column
  },
  //...
]
//...
const table = useReactTable({
  columns,
  data,
  enableMultiSort: false, // disable multi-sorting for the entire table
})
自定义多列排序触发器

默认情况下,Shift 键用于触发多列排序。您可以使用 isMultiSortEvent 表格选项更改此行为。您甚至可以指定所有排序事件都应通过从自定义函数返回 true 来触发多列排序。

jsx
const table = useReactTable({
  columns,
  data,
  isMultiSortEvent: (e) => true, // normal click triggers multi-sorting
  //or
  isMultiSortEvent: (e) => e.ctrlKey || e.shiftKey, // also use the `Ctrl` key to trigger multi-sorting
})
const table = useReactTable({
  columns,
  data,
  isMultiSortEvent: (e) => true, // normal click triggers multi-sorting
  //or
  isMultiSortEvent: (e) => e.ctrlKey || e.shiftKey, // also use the `Ctrl` key to trigger multi-sorting
})
多列排序限制

默认情况下,一次可以排序的列数没有限制。您可以使用 maxMultiSortColCount 表格选项设置限制。

jsx
const table = useReactTable({
  columns,
  data,
  maxMultiSortColCount: 3, // only allow 3 columns to be sorted at once
})
const table = useReactTable({
  columns,
  data,
  maxMultiSortColCount: 3, // only allow 3 columns to be sorted at once
})
移除多列排序

默认情况下,移除多列排序的功能已启用。您可以使用 enableMultiRemove 表格选项禁用此行为。

jsx
const table = useReactTable({
  columns,
  data,
  enableMultiRemove: false, // disable the ability to remove multi-sorts
})
const table = useReactTable({
  columns,
  data,
  enableMultiRemove: false, // disable the ability to remove multi-sorts
})

排序 API

有很多与排序相关的 API,您可以用来连接到您的 UI 或其他逻辑。以下是所有排序 API 及其一些用例的列表。

  • table.setSorting - 直接设置排序状态。

  • table.resetSorting - 将排序状态重置为初始状态或清除它。

  • column.getCanSort - 用于启用/禁用列的排序 UI。

  • column.getIsSorted - 用于显示列的视觉排序指示器。

  • column.getToggleSortingHandler - 用于连接列的排序 UI。添加到排序箭头(图标按钮)、菜单项或仅添加到整个列标题单元格。此处理程序将使用正确的参数调用 column.toggleSorting

  • column.toggleSorting - 用于连接列的排序 UI。如果使用它而不是 column.getToggleSortingHandler,您必须手动传入是否使用多列排序。(column.toggleSorting(desc, multi))

  • column.clearSorting - 用于特定列的“清除排序”按钮或菜单项。

  • column.getNextSortingOrder - 用于显示列接下来将按哪个方向排序。(在工具提示/菜单项/aria-label 中显示 asc/desc/clear 或其他内容)

  • column.getFirstSortDir - 用于显示列将首先按哪个方向排序。(在工具提示/菜单项/aria-label 中显示 asc/desc 或其他内容)

  • column.getAutoSortDir - 确定列的第一个排序方向是升序还是降序。

  • column.getAutoSortingFn - 在内部使用,以查找列的默认排序函数(如果未指定)。

  • column.getSortingFn - 返回用于列的确切排序函数。

  • column.getCanMultiSort - 用于启用/禁用列的多列排序 UI。

  • column.getSortIndex - 用于在多列排序场景中显示列的排序顺序的徽章或指示器。即,它是要排序的第一列、第二列、第三列等。

订阅 Bytes

您的每周 JavaScript 新闻。每周一免费发送给超过 10 万名开发者。

Bytes

无垃圾邮件。随时取消订阅。