🌲系列一:跟着官方示例学习 @tanStack-table --- Basic
🌲系列二:跟着官方示例学习 @tanStack-table --- Header Groups
👏 Sort
上次我们已经成功把表格渲染出来了,还用了 column group
做了结构分组。今天我们要给它加上「排序」的能力。
点击一下表头,就可以按升序、再点一下就降序、再点回到默认排序。是不是很熟悉?
🚦 第一步:启用排序功能
我们只需要在创建 table 的时候把它添加进去即可:
tsx
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(), // 👈 开启排序
});
🔎 getSortedRowModel 是一个内置的排序逻辑,它会根据你点击的列自动处理排序逻辑。
🧲 第二步:让表头"可以点击"
在渲染表头的时候,我们只需要加上一点交互行为,@tanstack/react-table 已经为我们准备好了相关的 API:
tsx
<div
className={header.column.getCanSort() ? 'cursor-pointer select-none' : ''}
onClick={header.column.getToggleSortingHandler()}
>
{flexRender(header.column.columnDef.header, header.getContext())}
{{
asc: ' 🔼',
desc: ' 🔽',
}[header.column.getIsSorted() as string] ?? null}
</div>
📌 分析一下这段代码在干什么:
getCanSort()
:判断当前列是否允许排序
getToggleSortingHandler()
:返回一个可以用于切换该列排序状态的函数
getIsSorted()
:告诉你当前列是否被排序了,是什么方向(升/降)
🔼 / 🔽 是我们手动加的图标,用来提示用户当前排序状态

🔔 对官方示例代码可能存在一些删减的情况
代码地址🔗:Gitee
官方代码地址🔗: @tanStack/react-table
🤝 Filter
可以理解为 Excel
中的"筛选器",根据你输入的关键词、选择的状态,甚至输入的数值范围来过滤你想看的行数据。
🛠 核心状态:columnFilters + getFilteredRowModel
过滤功能的核心只有两个部分:
1️⃣ 声明过滤状态
tsx
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]);
这是一个数组,记录了每一列当前的过滤条件。
2️⃣ useReactTable
过滤逻辑
tsx
const table = useReactTable({
//...
state: {
columnFilters,
},
onColumnFiltersChange: setColumnFilters,
getFilteredRowModel: getFilteredRowModel(), // 👈 启用内置过滤逻辑
});
只要你在列上调用了 setFilterValue(),就会更新 columnFilters 状态,并自动触发过滤逻辑。
🧩 渲染每列的过滤输入框
我们在表头中为每一列添加了一个 <Filter />
组件,渲染不同类型的过滤器:
tsx
{header.column.getCanFilter() ? (
<div>
<Filter column={header.column} />
</div>
) : null}
通过 getCanFilter()
API 🔗 判断是否启用过滤器,避免一些不可过滤的列出错。
🔀 三种不同的过滤器组件
我们根据列定义中 meta.filterVariant 的配置,渲染不同样式的过滤器输入框:
✅ 1. 文本过滤(默认)
tsx
<DebouncedInput
className="w-36 border shadow rounded"
onChange={(value) => column.setFilterValue(value)}
placeholder="Search..."
type="text"
value={(columnFilterValue ?? '') as string}
/>
适用于 firstName、lastName 等文本字段。
🧮 2. 范围过滤(range)
tsx
<div className="flex space-x-2">
<DebouncedInput
type="number"
value={(columnFilterValue as [number, number])?.[0] ?? ''}
onChange={(value) =>
column.setFilterValue((old: [number, number]) => [value, old?.[1]])
}
placeholder={`Min`}
className="w-24 border shadow rounded"
/>
<DebouncedInput
type="number"
value={(columnFilterValue as [number, number])?.[1] ?? ''}
onChange={(value) =>
column.setFilterValue((old: [number, number]) => [old?.[0], value])
}
placeholder={`Max`}
className="w-24 border shadow rounded"
/>
</div>
适用于 age、visits、progress 这种数值型列。
🧾 3. 下拉过滤(select)
tsx
<select
onChange={(e) => column.setFilterValue(e.target.value)}
value={columnFilterValue?.toString()}
>
<option value="">All</option>
<option value="complicated">complicated</option>
<option value="relationship">relationship</option>
<option value="single">single</option>
</select>
适用于枚举类型的字段,例如 status,用户可以直接选择"Single"、"Complicated" 等值进行筛选。
🔔 对官方示例代码可能存在一些删减的情况
代码地址🔗:Gitee
官方代码地址🔗: @tanStack/react-table

🔍 getFacetedRowModel 智能列过滤器
markdown
getFacetedRowModel
↓
getFacetedUniqueValues ← 用来生成下拉框 / datalist
getFacetedMinMaxValues ← 用来生成范围筛选器
✅ getFacetedUniqueValues 这个方法的作用是:
根据当前列的所有数据(在其它列过滤器生效的前提下)提取唯一值集合。
它通常用于构建下拉选择(select)或自动补全(datalist) 的过滤器。例如,性别列只会返回 ['Male', 'Female'],品牌列可能是 ['Nike', 'Adidas', 'Puma']。
⚠️ 注意:这个方法只会基于当前"可见数据"返回唯一值,意味着当用户先选了其他筛选条件时,这里的值也会动态变化,确保是"上下文相关"的。
✅ getFacetedMinMaxValues 这个方法的作用是:
返回当前列中的最小值和最大值,用于构建范围筛选器(如价格区间、年龄段等)。
比如在一个年龄列中,当前剩下的可选数据可能年龄范围是 [22, 45],这个 API 就会返回这个区间值,让你可以渲染一个最小值/最大值输入框,限制在合理范围内。

🔔 对官方示例代码可能存在一些删减的情况
代码地址🔗:Gitee
官方代码地址🔗: @tanStack/react-table
🔎 Fuzzy Filtering 模糊匹配过滤器
在表格搜索时,用户希望在搜索时不需要完全输入准确的值,也能快速定位目标数据。这时候,"模糊匹配过滤器"就派上用场了。
TanStack Table
支持自定义过滤器函数,我们可以结合 @tanstack/match-sorter-utils
提供的 rankItem
工具,轻松实现模糊匹配。
✨ 什么是模糊匹配(Fuzzy Matching)? 模糊匹配是一种容错搜索机制,它不要求用户输入的关键词与表格数据完全一致。
-
✅ 容忍拼写错误
-
✅ 忽略大小写
-
✅ 关键词顺序灵活
🧠 实现方式:自定义 fuzzyFilter 函数
tsx
import { rankItem } from '@tanstack/match-sorter-utils'
import { FilterFn } from '@tanstack/react-table'
// 自定义模糊匹配过滤函数
const fuzzyFilter: FilterFn<any> = (row, columnId, value, addMeta) => {
const itemRank = rankItem(row.getValue(columnId), value)
addMeta({ itemRank }) // 可选:供排序使用
return itemRank.passed
}
🔌 使用方式 在 useReactTable 中将它挂载到 filterFns 上:
tsx
const table = useReactTable({
data,
columns,
filterFns: {
fuzzy: fuzzyFilter,
},
globalFilterFn: 'fuzzy', // 全局搜索启用模糊匹配
...
})
在列中启用模糊过滤:
tsx
{
accessorKey: 'fullName',
header: 'Full Name',
filterFn: 'fuzzy', // 列级别启用 fuzzy
}
💡 模糊匹配 + 排序联动 模糊搜索通常会用 rankItem.score 来排序最相关的结果,你还可以监听过滤状态,自动对当前列排序:
tsx
React.useEffect(() => {
if (table.getState().columnFilters[0]?.id === 'fullName') {
if (table.getState().sorting[0]?.id !== 'fullName') {
table.setSorting([{ id: 'fullName', desc: false }])
}
}
}, [table.getState().columnFilters[0]?.id])
TanStack Table
内置了一些 filter function
API🔗
tsx
{
accessorKey: 'id',
filterFn: 'equalsString', // note: normal non-fuzzy filter column - exact match required
},
{
accessorKey: 'firstName',
filterFn: 'includesStringSensitive', // note: normal non-fuzzy filter column - case sensitive
},
{
accessorKey: 'lastName',
filterFn: 'includesString', // note: normal non-fuzzy filter column - case insensitive
},

🔔 对官方示例代码可能存在一些删减的情况
代码地址🔗:Gitee
官方代码地址🔗: @tanStack/react-table