ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Refine 与 TanStack Table 集成实战:用 useTable 实现列级筛选(Column Filtering)

Refine 与 TanStack Table 集成实战:用 useTable 实现列级筛选(Column Filtering) Refine 与 TanStack Table 集成实战用 useTable 实现列级筛选Column Filtering【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine本文围绕 Refine 仓库中 refinedev/react-table 的列级筛选 Live Preview 示例documentation/docs/packages/tanstack-table/examples/_partial-filtering-live-preview.md展开讲解如何用useTable把 TanStack Table 的列筛选状态与 Refine 的服务端过滤CrudFilters打通并通过meta.filterOperator精确控制每个字段的过滤算子。读完本文你将掌握如何在 headless 表格中渲染可筛选表头、如何将列筛选翻译成 Refine 数据提供者能识别的过滤条件以及条件过滤and/or和filterKey的使用方式。一、背景无头表格适配器如何工作Refine 通过 TanStack Table 集成介绍 提供了refinedev/react-table这个适配器包它让你在使用 TanStack Table 的同时自动继承 RefineuseTable的分页、排序、过滤等全部能力。底层数据获取走的是useList即 data provider 的getList同时因为它被设计为headlessUI 渲染完全由你控制。安装方式npm install refinedev/react-table从源码看这个适配器的入口定义在 packages/react-table/src/useTable/index.ts内部先调用核心包的useTableuseTableCore拿到filters、setFilters、sorters、currentPage等 Refine 状态再调用useReactTable创建 TanStack Table 实例通过一组工具函数在「TanStack 列筛选状态ColumnFiltersState」与「Refine 过滤状态CrudFilters」之间做双向翻译。其中的关键开关manualPagination: true分页始终由服务端Refine 数据提供者控制manualSorting: isServerSideFilteringEnabled只有当sorters.mode不是off时才开启服务端排序manualFiltering: isServerSideFilteringEnabled只有当filters.mode不是off时才开启服务端过滤此时getFilteredRowModel()不会被挂载。也就是说默认情况下每次筛选变化都会触发一次新的数据请求。二、核心示例可筛选的 PostList 表格下面是被嵌入useTable文档 Filtering 小节的可运行示例去掉 Live Preview 包装后的核心代码完整源码见 examples/_partial-filtering-live-preview.mdimport React from react; import { useTable } from refinedev/react-table; import { ColumnDef, flexRender } from tanstack/react-table; interface IPost { id: number; title: string; content: string; status: published | draft | rejected; } const PostList: React.FC () { const columns React.useMemoColumnDefIPost[]( () [ { id: id, header: ID, accessorKey: id, enableColumnFilter: false, // 该列禁用列筛选 }, { id: title, header: Title, accessorKey: title, meta: { filterOperator: contains, // 使用模糊包含匹配 }, }, { id: status, header: Status, accessorKey: status, meta: { filterOperator: contains, }, }, { id: createdAt, header: CreatedAt, accessorKey: createdAt, meta: { filterOperator: gte, // 使用大于等于 }, }, ], [], ); const { reactTable: { getHeaderGroups, getRowModel }, } useTable({ columns, }); return ( table thead {getHeaderGroups().map((headerGroup) ( tr key{headerGroup.id} {headerGroup.headers.map((header) { return ( th key{header.id} {header.isPlaceholder ? null : ( {flexRender( header.column.columnDef.header, header.getContext(), )} {header.column.getCanFilter() ? ( div input value{ (header.column.getFilterValue() as string) ?? } onChange{(e) header.column.setFilterValue(e.target.value) } / /div ) : null} / )} /th ); })} /tr ))} /thead tbody {getRowModel().rows.map((row) { return ( tr key{row.id} {row.getVisibleCells().map((cell) { return ( td key{cell.id} {flexRender(cell.column.columnDef.cell, cell.getContext())} /td ); })} /tr ); })} /tbody /table ); };这个示例演示了三个关键知识点筛选 UI 由你手写header.column.getCanFilter()判断该列是否允许筛选对应enableColumnFilter: false的id列就不会渲染输入框受控输入绑定输入框的value来自header.column.getFilterValue()onChange调用header.column.setFilterValue()meta.filterOperator决定服务端算子title/status用containscreatedAt用gteid列明确关闭筛选。三、从列筛选到 CrudFilters底层翻译逻辑TanStack Table 的筛选状态只是一个{ id, value }列表但 Refine 的数据提供者需要的是带operator的CrudFiltersLogicalFilter或ConditionalFilter。二者之间的翻译由适配器自动完成。3.1 默认算子在 packages/react-table/src/utils/column-filters-to-crud-filters/index.ts 中翻译规则为优先读取列定义meta.filterOperator若未声明则根据值的类型取默认值为数组时用in否则用eq。测试用例 column-filters-to-crud-filters/index.spec.ts 直接验证了这一行为{ id: name, value: John }会翻译成{ field: name, operator: eq, value: John }而数组值[John, Doe]会被翻译成operator: in。3.2 组合过滤and / or当meta.filterOperator为and或or且筛选值是一个数组时会产生ConditionalFilter结构{ key: filterKey, // 默认取列 id operator: or, // 或 and value: [ ...子过滤条件... ], }crudFiltersToColumnFilters反向翻译时会通过meta.filterKey找到对应的列 id见 crud-filters-to-column-filters/index.ts。适配器测试对「组合过滤」和「自定义filterKey」都有覆盖index.spec.ts。3.3 已移除筛选的同步当某列筛选被清空时适配器通过getRemovedFilters把对应条件以value: undefined的形式补回确保 Refine 侧的filters状态被完整同步见 get-removed-filters/index.ts。3.4 筛选变化时的行为在 useTable/index.ts 中useEffect监听columnFilters将其翻译后通过setFilters写入 Refine若当前存在筛选且分页开启还会自动把页码重置回第 1 页setCurrentPage(1)避免停留在筛选结果之外的分页上。四、配套属性如何控制过滤行为以下属性都在useTable({ refineCoreProps: {...} })中配置详见 useTable Hook 文档属性取值默认值说明filters.modeserver/offserveroff时不把筛选发送给服务端配合 TanStack Table 客户端筛选getFilteredRowModel会被启用filters.initialCrudFilter[]—初始筛选值用户修改后即被清除filters.permanentCrudFilter[]—永久筛选值不可被用户操作清除filters.defaultBehaviormerge/replacereplace新筛选如何与现有筛选合并merge按列合并replace整体替换syncWithLocationboolean来自Refine开启后筛选、排序、分页状态会编码进 URL query支持分享/书签特定表格视图服务端过滤开关manualFiltering正是由filters.mode推导而来useTable/index.ts这解释了为什么filters.mode: off可以无缝切换到 TanStack 自带的客户端过滤——此时适配器不再把getFilteredRowModel禁用。读取当前筛选值Refine 提供了getDefaultFilter工具从refineCore.filters中取出指定字段的筛选值import { getDefaultFilter } from refinedev/core; import { useTable } from refinedev/react-table; const MyComponent () { const { refineCore: { filters }, } useTable({ refineCoreProps: { filters: { initial: [ { field: name, operator: contains, value: John Doe }, ], }, }, }); const nameFilterValue getDefaultFilter(name, filters, contains); console.log(nameFilterValue); // John Doe return { /* ... */ }; };getDefaultFilter的实现位于核心包的src/definitions/table/index.ts对应 packages/core 目录适合在需要把筛选值回填到表单、下拉框或自定义筛选面板时使用。五、实践要点与注意事项5.1 完整示例运行环境该 Live Preview 示例的宿主代码会在启动时执行setInitialRoutes([/posts])并将PostList挂载到RefineHeadlessDemo下的/posts路由。你需要一个带posts资源的 Refine 应用例如参考仓库中的 table-react-table-basic 示例useTable文档底部即引用此示例。resource默认从当前路由读取也可以通过refineCoreProps.resource显式指定。5.2 常见问题为什么id列不显示筛选框因为设置了enableColumnFilter: falsegetCanFilter()返回false为什么每次输入都触发请求默认filters.mode: server列筛选状态一旦变化就会通过setFilters触发getList重新请求如果希望纯客户端过滤设置filters.mode: off即可FAQ 章节 也推荐了这一做法filterOperator必须是CrudOperators类型包括eq、ne、lt、lte、gt、gte、contains、ncontains、in、nin、between、and、or等具体以核心包的CrudOperators定义为准组合过滤的key默认取列 id多个相同算子并存时用meta.filterKey区分不同条件。六、小结列级筛选是 TanStack Table 与 Refine 数据层整合最典型的场景UI 完全 headless一个input即可状态同步则由refinedev/react-table的工具函数自动完成。掌握了meta.filterOperator、filters.mode与syncWithLocation这几个核心配置你就可以在任何 UI 库Ant Design、MUI、Mantine、Chakra UI 或原生 HTML之上快速构建出支持服务端过滤、可分享 URL 状态的管理后台表格。延伸阅读本示例是 useTable Hook 文档 中 Filtering 小节的组成部分同系列还有分页Pagination、排序Sorting、关联数据Relational等 Live Preview 示例均位于 documentation/docs/packages/tanstack-table/examples 目录下相关可运行工程可参考 examples/table-react-table-basic。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表