Lzh on GitHub

示例

想跳过直接看实现?请查看这些示例:

全局过滤指南

过滤分为两种:列过滤全局过滤

本指南将重点介绍全局过滤,它是一种应用于所有列的过滤器。

客户端过滤 vs 服务器端过滤

如果您的数据集很大,您可能不想将所有数据加载到客户端浏览器中进行过滤。在这种情况下,您很可能需要实现服务器端过滤、排序、分页等。

然而,正如分页指南中也讨论的,许多开发者低估了在不影响性能的情况下可以在客户端加载的行数。TanStack Table 的示例经常测试处理多达 100,000 行或更多的数据,并在客户端过滤、排序、分页和分组方面表现出不错的性能。这并不意味着您的应用程序能够处理那么多行,但是如果您的表格最多只有几千行,您也许可以利用 TanStack Table 提供的客户端过滤、排序、分页和分组功能。

TanStack Table 可以很好地处理数千个客户端行,性能良好。在没有经过一些思考之前,不要排除客户端过滤、分页、排序等。

每个用例都不同,将取决于表格的复杂性、您有多少列、每条数据的大小等等。需要注意的主要瓶颈是:

  • 您的服务器能否在合理的时间(和成本)内查询所有数据?
  • 获取的总大小是多少?(如果您没有很多列,这可能不会像您想象的那么糟糕。)
  • 如果所有数据都一次性加载,客户端浏览器是否会占用过多内存?

如果您不确定,您始终可以从客户端过滤和分页开始,然后随着数据增长在未来切换到服务器端策略。

手动服务器端全局过滤

如果您已决定需要实现服务器端全局过滤而不是使用内置的客户端全局过滤,以下是实现方法。

手动服务器端全局过滤不需要 getFilteredRowModel 表格选项。相反,您传递给表格的 data 应该已经过过滤。但是,如果您已经传递了 getFilteredRowModel 表格选项,您可以通过将 manualFiltering 选项设置为 true 来告诉表格跳过它。

const table = useReactTable({
  data,
  columns,
  // getFilteredRowModel: getFilteredRowModel(), // 手动服务器端全局过滤不需要
  manualFiltering: true,
})

注意:使用手动全局过滤时,本指南其余部分讨论的许多选项将不起作用。当 manualFiltering 设置为 true 时,表格实例将不会对传递给它的行应用任何全局过滤逻辑。相反,它将假定这些行已经过过滤,并将按原样使用您传递给它的 data

客户端全局过滤

如果您正在使用内置的客户端全局过滤功能,首先您需要将 getFilteredRowModel 函数传递给表格选项。

import { useReactTable, getFilteredRowModel } from '@tanstack/react-table'

//...

const table = useReactTable({
  // 其他选项...
  getCoreRowModel: getCoreRowModel(),
  getFilteredRowModel: getFilteredRowModel(), // 客户端全局过滤需要
})

全局过滤函数

globalFilterFn 选项允许您指定将用于全局过滤的过滤函数。过滤函数可以是引用内置过滤函数的字符串、引用通过 tableOptions.filterFns 选项提供的自定义过滤函数的字符串,或一个自定义过滤函数。

const table = useReactTable({
  data,
  columns,
  getCoreRowModel: getCoreRowModel(),
  getFilteredRowModel: getFilteredRowModel(),
  globalFilterFn: 'text' // 内置过滤函数
})

默认情况下有 10 个内置的过滤函数可供选择:

  • includesString - 不区分大小写的字符串包含
  • includesStringSensitive - 区分大小写的字符串包含
  • equalsString - 不区分大小写的字符串相等
  • equalsStringSensitive - 区分大小写的字符串相等
  • arrIncludes - 数组内项包含
  • arrIncludesAll - 数组包含所有项
  • arrIncludesSome - 数组包含部分项
  • equals - 对象/引用相等 Object.is/===
  • weakEquals - 弱对象/引用相等 ==
  • inNumberRange - 数字范围包含

您还可以将自己的自定义过滤函数定义为 globalFilterFn 表格选项。

全局过滤状态

全局过滤状态存储在表格的内部状态中,可以通过 table.getState().globalFilter 属性访问。如果您想在表格外部持久化全局过滤状态,您可以使用 onGlobalFilterChange 选项提供一个回调函数,当全局过滤状态更改时将调用该函数。

const [globalFilter, setGlobalFilter] = useState<any>([])

const table = useReactTable({
  // 其他选项...
  state: {
    globalFilter,
  },
  onGlobalFilterChange: setGlobalFilter
})

全局过滤状态定义为具有以下形状的对象:

interface GlobalFilter {
  globalFilter: any
}

将全局过滤器输入添加到 UI

TanStack Table 不会为您的表格添加全局过滤器输入 UI。您应该手动将其添加到您的 UI 中,以允许用户过滤表格。例如,您可以在表格上方添加一个输入 UI,以允许用户输入搜索词。

return (
  <div>
    <input
      value=""
      onChange={e => table.setGlobalFilter(String(e.target.value))}
      placeholder="搜索..."
    />
  </div>
)

自定义全局过滤函数

如果您想使用自定义全局过滤函数,您可以定义该函数并将其传递给 globalFilterFn 选项。

注意:通常,使用模糊过滤函数进行全局过滤是一个流行的想法。这在模糊过滤指南中进行了讨论。

const customFilterFn = (rows, columnId, filterValue) => {
  // 自定义过滤逻辑
}

const table = useReactTable({
  // 其他选项...
  globalFilterFn: customFilterFn
})

初始全局过滤状态

如果您想在表格初始化时设置初始全局过滤状态,您可以将全局过滤状态作为表格 initialState 选项的一部分传递。

但是,您也可以直接在 state.globalFilter 选项中指定初始全局过滤状态。

const [globalFilter, setGlobalFilter] = useState("搜索词") // 建议在此处初始化 globalFilter 状态

const table = useReactTable({
  // 其他选项...
  initialState: {
    globalFilter: '搜索词', // 如果不管理 globalFilter 状态,在此处设置初始状态
  },
  state: {
    globalFilter, // 将我们管理的 globalFilter 状态传递给表格
  }
})

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

禁用全局过滤

默认情况下,所有列都启用了全局过滤。您可以使用 enableGlobalFilter 表格选项来禁用所有列的全局过滤。您还可以通过将 enableFilters 表格选项设置为 false 来关闭列过滤和全局过滤。

禁用全局过滤将导致该列的 column.getCanGlobalFilter API 返回 false

const columns = [
  {
    header: () => 'ID',
    accessorKey: 'id',
    enableGlobalFilter: false, // 禁用此列的全局过滤
  },
  //...
]

const table = useReactTable({
  // 其他选项...
  columns,
  enableGlobalFilter: false, // 禁用所有列的全局过滤
})