Refine Table Search 实战:用 useTable 的 searchFormProps 与 onSearch 实现列表页搜索过滤

发布时间:2026/9/13 8:27:05
Refine Table Search 实战:用 useTable 的 searchFormProps 与 onSearch 实现列表页搜索过滤 Refine Table Search 实战用 useTable 的 searchFormProps 与 onSearch 实现列表页搜索过滤【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine本文基于 Refine 官方进阶教程文档Table Search完整讲解如何在列表页利用useTableHook 构建搜索表单、通过onSearch将表单值转换为CrudFilters并结合开源仓库中的 Hook 源码剖析「表单提交 → 过滤条件生成 → 查询刷新」的完整调用链与类型约束帮助你在 Ant Design 项目如pankod/refine-antd/refinedev/antd中快速落地可扩展的表格搜索/过滤功能。整体思路searchFormProps onSearch在 Refine 中列表页的复杂搜索与过滤统一由useTableHook 驱动。其核心设计分为两步对应官方文档 table-search.md 的主线构建搜索表单从useTable解构出searchFormProps将其展开到 antdForm上表单字段的name即为搜索变量名转换过滤条件通过onSearch回调接收表单提交的值返回一个CrudFilters对象Refine 会据此重新发起useList查询。这种「表单值 → 过滤器数组」的解耦方式意味着表单 UI 想怎么设计都可以输入框、日期范围、下拉框……最终都收敛为统一、可被任意 dataProvider 理解的CrudFilters结构搜索条件与数据层彻底分离。第一步用 searchFormProps 创建搜索表单按照文档给出的示例在列表页pages/list.tsx中引入Form、Table、useTable等组件并从useTableIPost()中取出searchFormPropsimport { // highlight-start Form, Table, useTable, // highlight-end Row, Col, Icons, List, Button, DatePicker, Space, Input, } from pankod/refine-antd; const { RangePicker } DatePicker; export const ListPage: React.FC () { // highlight-next-line const { searchFormProps } useTableIPost(); return ( // highlight-start Row gutter{[16, 16]} Col lg{6} xs{24} Form layoutvertical {...searchFormProps} Form.Item labelSearch nameq Input placeholderID, Title, Content, etc. prefix{Icons.SearchOutlined /} / /Form.Item Form.Item labelCreated At namecreatedAt RangePicker / /Form.Item Form.Item Button htmlTypesubmit typeprimary Filter /Button /Form.Item /Form /Col Col lg{18} xs{24} List Table.../Table /List /Col /Row // highlight-end ); }; interface IPost { id: number; title: string; createdAt: string; }要点说明Form layoutvertical {...searchFormProps}searchFormProps是一个标准的 antdFormProps在源码中类型为FormPropsTSearchVariables直接展开即可让表单接管onFinish等生命周期Form.Item的name决定搜索变量上例中nameq与namecreatedAt会分别成为onSearch(params)参数里的q与createdAt字段布局上推荐用Row/Col把搜索表单放在左侧窄栏lg{6} xs{24}、表格放在右侧宽栏lg{18} xs{24}在小屏下自动堆叠为全宽。第二步onSearch 将表单值转换为 CrudFilters文档强调当表单提交后onSearch方法会被执行并拿到搜索表单的值你需要为该回调返回一个CrudFilters类型的对象。完整示例注意这里为useTable提供了第三个泛型参数用于声明搜索变量类型... import { HttpError } from pankod/refine-core; import { Dayjs } from dayjs; const { searchFormProps } useTable IPost, HttpError, { title: string; createdAt: [Dayjs, Dayjs] } ({ onSearch: (params) { const filters: CrudFilters []; const { q, createdAt } params; filters.push( { field: q, operator: eq, value: q, }, { field: createdAt, operator: gte, value: createdAt ? createdAt[0].toISOString() : undefined, }, { field: createdAt, operator: lte, value: createdAt ? createdAt[1].toISOString() : undefined, }, ); return filters; }, }); ...文档中特别以 caution 提示CrudFilters中的每个对象包含field、operator、value三个属性它们共同描述「在哪个字段上、用什么操作符、以什么值进行过滤」。从源码看onSearch 之后发生了什么结合仓库中 antd 适配包的 Hook 实现useTable.ts可以看到整条链路类型契约useTableProps在 core 返回类型之上扩展了onSearch?: (data: TSearchVariables) CrudFilters | PromiseCrudFilters见 useTable.ts因此onSearch既支持同步返回也支持async写法例如先从接口取选项列表再构造过滤器表单接管Hook 内部通过 antd 的Form.useFormTSearchVariables()创建表单实例并返回searchFormProps: { ...formSF.formProps, onFinish }见 useTable.ts——这正是第一步中Form展开的属性的来源提交触发过滤与重置分页内部onFinish在表单提交时执行const searchFilters await onSearch(value); setFilters(searchFilters);并在分页开启时调用setCurrentPage?.(1)见 useTable.ts。也就是说每次搜索都会把filters状态替换为你返回的条件并把表格重置回第 1 页随后 core 层的tableQuery依据新的filters重新请求数据URL 同步Hook 中还包含syncWithLocation相关逻辑——开启同步后会读取表单中已注册的字段名从当前filters中找到同名字段并把值回填到表单见 useTable.ts。从源码结构看这意味着搜索条件可随 URL 分享/刷新还原是搭建「可分享的筛选视图」的基础能力。CrudFilters 结构详解字段、操作符与值CrudFilters的精确定义在 types.tsexport type LogicalFilter { field: string; operator: ExcludeCrudOperators, or | and; value: any; }; export type ConditionalFilter { key?: string; operator: ExtractCrudOperators, or | and; value: (LogicalFilter | ConditionalFilter)[]; }; export type CrudFilter LogicalFilter | ConditionalFilter; export type CrudFilters CrudFilter[];即过滤器分为两类LogicalFilter文档示例中使用的常规形式fieldoperatorvalue三元组ConditionalFilter用operator: or | and组合一组子过滤器可嵌套用于表达「满足任一条件」等复杂逻辑。CrudOperators支持的完整操作符列表同样定义于 types.ts操作符含义eq/ne等于 / 不等于eqs/nes等于 / 不等于区分大小写lt/gt/lte/gte小于 / 大于 / 小于等于 / 大于等于in/nin在数组内 / 不在数组内ina/nina部分元素在数组内 / 不在数组内contains/ncontains包含 / 不包含containss/ncontainss包含 / 不包含区分大小写between/nbetween区间内 / 区间外null/nnull为空 / 不为空startswith/nstartswith含s大小写敏感变体前缀匹配及其否定endswith/nendswith含s大小写敏感变体后缀匹配及其否定or/and逻辑组合仅用于ConditionalFilter文档示例中的日期范围搜索正是「一个字段两个条件」的典型写法createdAt分别用gte大于等于起始时间与lte小于等于结束时间约束RangePicker返回的[Dayjs, Dayjs]通过toISOString()转成标准时间字符串未选择时传undefined由 dataProvider 忽略。如果后端支持更紧凑的写法也可以用between操作符把两个边界合并为一个过滤器——具体以你的 dataProvider 文档为准。版本适用性说明需要留意本教程文档面向 Refine v3pankod/refine-antd/pankod/refine-core包命名而当前仓库主干的 antd 适配包已从pankod/refine-antd迁移为refinedev/antd、核心逻辑迁移至refinedev/core见 useTable.ts 中的 import 来源。searchFormPropsonSearch返回CrudFilters的使用模式在两个版本中一致迁移时主要替换包名与个别类型导入路径即可搜索表单的写法不受影响。参考示例table-antd-table-filter文档末尾的 ExampleCodeSandboxtable-antd-table-filter对应仓库中的完整可运行项目 examples/table-antd-table-filter。其列表页 list.tsx 展示了生产级用法const { tableProps, searchFormProps } useTable...({ onSearch: (params) { // ...将 params 转换为 CrudFilters }, }); // ... Filter formProps{searchFormProps} /可以看到它把searchFormProps作为formProps传给了一个可复用的Filter封装组件与Table {...tableProps} /搭配即「搜索表单组件 表格组件」的组合模式。建议在本地安装依赖后运行该示例直观体验提交搜索表单后表格数据、分页与 URL 的联动效果。小结搜索表单由searchFormProps驱动Form.Item的name即搜索变量名表单 UI 与过滤逻辑彻底解耦onSearch是唯一的「翻译层」把任意形态的表单值转换为CrudFilters返回后 Refine 自动重置到第 1 页并重新查询CrudFilters的field/operator/value三元组覆盖等值、区间、包含、前缀、空值及or/and组合等绝大多数查询场景且可被任意 dataProviderREST、GraphQL、Supabase 等统一消费结合syncWithLocation搜索条件还能同步到 URL实现可分享、可刷新还原的筛选视图。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考