ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Refine v5 基础表格实战:使用 @refinedev/react-table 与 Chakra UI 构建服务端驱动表格

Refine v5 基础表格实战:使用 @refinedev/react-table 与 Chakra UI 构建服务端驱动表格 Refine v5 基础表格实战使用 refinedev/react-table 与 Chakra UI 构建服务端驱动表格【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine本篇技术指南围绕 Refine v5 官方示例table-chakra-ui-basic对应文档 basic.md展开讲解如何借助refinedev/react-table适配器在 Chakra UI 项目中直接使用 TanStack TableReact Table的全部能力并让排序、筛选、分页等操作全部落到服务端数据源。读完本文你将掌握从列定义、服务端排序/筛选、分页组件到关联数据展示的完整实现路径并理解适配器在 Refine Core 与 React Table 之间的双向同步原理。示例定位一张服务端驱动的基础表格Refine 的核心设计之一是headless 灵活性它不绑定任何 UI 库而是通过适配器把数据层能力注入你选定的组件生态。在表格领域这一角色由refinedev/react-table承担——它基于 TanStack Table 构建让开发者可以直接使用 React Table 的全部特性列配置、排序、筛选、分页、行模型等同时这些状态变化会被同步到 Refine Core 的useTable最终反映为对数据提供者的真实请求参数。table-chakra-ui-basic正是这一能力在 Chakra UI 下的最小完整示例一张 posts 列表支持列头排序、列头筛选、分页并且所有操作都是服务端模式server-side即数据由 API 按需返回而非一次性拉全量后在浏览器内存中处理。该示例的核心依赖见 package.jsonrefinedev/react-tableRefine 与 TanStack Table 的适配层tanstack/react-table底层表格引擎refinedev/chakra-ui提供List、DateField、ShowButton、EditButton、DeleteButton、usePagination等 Refine 组件与 Hookchakra-ui/reactUI 组件库refinedev/simple-rest示例数据提供者请求https://api.fake-rest.refine.devrefinedev/react-router路由提供者。如何运行该示例npm create refine-applatest -- --example table-chakra-ui-basic命令会以官方模板脚手架的方式在本地生成完整项目随后npm install并npm run dev即可启动。应用入口 main.tsx 与 App.tsx 中可以看到标准装配ChakraProvider主题RefineThemes.Blue包裹Refine注册routerProvider、dataProvider与posts资源并开启syncWithLocation与warnWhenUnsavedChanges——前者保证筛选/排序/分页状态可随 URL 同步后者在离开未保存表单时给出提示。第一步用 useTable 把 Refine Core 与 React Table 接通列表页核心在 list.tsx。它从refinedev/react-table引入useTable并解构出两个命名空间const { reactTable: { getHeaderGroups, getRowModel, setOptions }, refineCore: { setCurrentPage: setCurrent, pageCount, currentPage: current, tableQuery: { data: tableData }, }, } useTable({ columns, refineCoreProps: { sorters: { initial: [{ field: id, order: desc }], }, }, });reactTableTanStack Table 实例负责列头渲染、行模型、排序/筛选的 UI 状态refineCoreRefine CoreuseTable的返回值负责分页、排序、筛选的服务端状态与数据请求。refineCoreProps会把配置透传给 Core 的useTable。示例中通过sorters.initial设置了默认排序按id降序。也就是说页面首次加载时就会带上sorters[0]id.desc这样的请求参数配合syncWithLocation该默认排序还会体现在 URL 中。在适配器内部见 packages/react-table/src/useTable/index.tsuseTable先调用 Core 的useTable拿到tableQuery、setCurrentPage、setPageSize、setSorters、setFilters、pageCount等再调用useReactTable构建表格实例并把服务端模式显式写入manualPagination: true, manualSorting: isServerSideSortingEnabled, manualFiltering: isServerSideFilteringEnabled,其中isServerSideSortingEnabled由refineCoreProps.sorters?.mode默认server决定筛选同理默认server。当manualSorting/manualFiltering为true时TanStack Table 不会在本地排序/过滤数据而是把状态变化抛给上层由 Refine 转成 CRUD 请求参数。这正是本示例服务端驱动的底层开关。第二步列定义ColumnDef列通过React.useMemo包裹的ColumnDefIPost[]定义类型模型见 interfaces/index.d.tsexport interface IPost { id: number; title: string; content: string; status: published | draft | rejected; category: { id: number }; }示例共定义 6 列id、title、status、category.id、createdAt、actions。其中值得注意的配置accessorKey直接绑定数据字段enableColumnFilter: false该列不出现筛选入口如id、category.id、createdAt、actionsenableSorting: false操作列不可排序meta存放 Refine 扩展信息包括filterOperator与自定义filterElement见下文筛选部分cell自定义单元格渲染可接收getValue、table等上下文。第三步列头排序与筛选组件列头由getHeaderGroups()渲染每个Th内除了标题文本还挂载了自定义的ColumnSorter与ColumnFilter见 columnSorter.tsx 与 columnFilter.tsx。ColumnSorter切换排序方向export const ColumnSorter: React.FCColumnButtonProps ({ column }) { if (!column.getCanSort()) return null; const sorted column.getIsSorted(); return ( IconButton aria-labelSort sizexs onClick{column.getToggleSortingHandler()} style{{ transform: rotate(${sorted asc ? 180 : 0}deg), transition: transform 0.25s, }} variant{sorted ? light : transparent} icon{!sorted ? IconSelector size{18} / : IconChevronDown size{18} /} / ); };逻辑要点通过column.getToggleSortingHandler()复用 TanStack Table 的排序切换逻辑asc → desc → 无getIsSorted()返回asc/desc/false据此旋转图标升序时箭头向上旋转 180°并切换按钮配色。由于适配器开启了manualSorting点击后排序状态会被同步回 Refine最终以sorters[]参数请求服务端。ColumnFilter弹出式筛选菜单ColumnFilter使用 Chakra UI 的Menu组件实现点击图标弹出筛选输入框默认渲染Input文本输入框若列在meta.filterElement中提供了自定义筛选元素则优先渲染该元素提供清除column.setFilterValue(undefined)与保存column.setFilterValue(state.value)两个操作。在list.tsx中title列通过meta.filterOperator: contains指定服务端使用包含匹配status列则同时指定了filterOperator: eq和自定义filterElement——一个包含 published / draft / rejected 三个选项的下拉框{ id: status, header: Status, accessorKey: status, meta: { filterElement: ({ value, onChange }) ( Select borderRadiusmd sizesm placeholderAll Status {...{ value, onChange }} option valuepublishedpublished/option option valuedraftdraft/option option valuerejectedrejected/option /Select ), filterOperator: eq, }, },这里的filterOperator会被适配器转换为 CRUD 筛选对象。在 column-filters-to-crud-filters 中列筛选columnFilters会结合列的meta.filterOperator生成形如{ field, operator: contains | eq, value }的CrudFilter最终由数据提供者拼接为?title_likexxxstatuspublished之类的查询参数。第四步服务端分页与自定义分页组件分页同样走服务端模式。useTable的refineCore返回currentPage、pageCount、setCurrentPage示例把它们传给自定义的 Paginationexport const Pagination: FCPaginationProps ({ current, pageCount, setCurrent }) { const pagination usePagination({ current, pageCount }); // ... };usePagination来自refinedev/chakra-ui根据当前页与总页数计算出一组可点击的页码条目含...省略号返回items、prev、next。渲染逻辑pagination.prev存在时渲染上一页图标按钮点击setCurrent(current - 1)遍历pagination.items字符串项渲染为...数字项渲染为页码按钮当前页用solid变体高亮pagination.next存在时渲染下一页按钮。点击任意页码都会调用setCurrent进而触发 Refine 以current页码和pageSize参数重新请求数据。在适配器内部TanStack Table 的pagination.pageIndex变化会通过useEffect回写setCurrentPage(pageIndex 1)见 useTable/index.ts这就是点击表格自带分页状态也能驱动服务端请求的双向同步机制。同样排序或筛选状态变化时适配器还会自动把页码重置为 1避免停留在越界页见 useTable/index.ts。第五步关联数据展示useMany table metacategory.id列只保存了外键 ID显示时需要联查categories资源。示例使用useManyconst categoryIds tableData?.data?.map((item) item.category.id) ?? []; const { result: categoriesData } useManyICategory({ resource: categories, ids: categoryIds, queryOptions: { enabled: categoryIds.length 0 }, });然后通过setOptions把categoriesData注入表格的metasetOptions((prev) ({ ...prev, meta: { ...prev.meta, categoriesData }, }));单元格渲染时从table.options.meta读取这份数据并查找匹配项cell: ({ getValue, table }) { const meta table.options.meta as { categoriesData: GetManyResponseICategory }; const category meta.categoriesData?.data.find((item) item.id getValue()); return category?.title ?? Loading...; },这是 TanStack Table 官方的meta扩展点与 Refine 数据 Hook 结合的典型用法数据通过useMany一次批量获取避免逐行发请求查询未返回前显示 Loading... 占位。第六步操作列与日期字段actions列使用refinedev/chakra-ui提供的三个按钮通过recordItemId绑定当前行 IDhideText只显示图标、sizesm紧凑布局HStack ShowButton hideText sizesm recordItemId{getValue() as number} / EditButton hideText sizesm recordItemId{getValue() as number} / DeleteButton hideText sizesm recordItemId{getValue() as number} / /HStack这三个按钮会自动感知资源的路由定义/posts/show/:id、/posts/edit/:id以及删除确认与通知逻辑。createdAt列则用DateField格式化展示cell: ({ getValue }) DateField value{getValue() as string} formatLLL /,DateField是 Refine 提供的按资源i18nlocale 渲染日期的字段组件formatLLL输出类似 Sep 11, 2026 8:30 PM 的可读格式。适配器原理refineCore 与 reactTable 的双向同步抛开示例看本质refinedev/react-table的核心价值在于四个方向的同步全部可在 useTable/index.ts 中验证数据流useReactTable({ data: tableQuery.data?.data ?? [] })服务端返回的当前页数据作为表格数据源分页同步useEffect监听pagination.pageIndex变化调用setCurrentPage(pageIndex 1)pageSize变化调用setPageSizeCore排序同步useEffect监听sorting将其映射为CrudSortingfieldorder后setSorters同时重置页码筛选同步useEffect通过 column-filters-to-crud-filters 把columnFilters结合列meta.filterOperator转成CrudFilter[]再叠加 get-removed-filters 计算出的已删除筛选最终setFilters。反向从 URL/外部状态恢复表格 UI则由 crud-filters-to-column-filters 在initialState.columnFilters中完成配合syncWithLocation刷新页面后排序与筛选依然保留。这些工具函数都有配套单元测试如 column-filters-to-crud-filters/index.spec.ts可作为理解映射规则的最小文档。另外packages/react-table导出的适配器同样适用于其他 UI 栈无 UI 依赖纯 headlessChakra UI 侧只负责把状态渲染成组件本示例的分页复用refinedev/chakra-ui的usePagination若使用其他 UI 库可自行实现同等分页逻辑。验证与测试仓库为每个示例都配套了 Cypress E2E 测试本示例对应 cypress/e2e/table-chakra-ui-basic。测试覆盖了关键交互表格行渲染、列排序点击后的服务端请求、筛选输入后的列表变化、分页跳转等可作为示例行为是否符合预期的可执行验收依据。小结通过table-chakra-ui-basic示例可以看到在 Refine v5 中构建一张开箱即用的服务端表格只需三步用refinedev/react-table的useTable声明列与refineCoreProps用 Chakra UI 组件渲染getHeaderGroups()与getRowModel()并挂上排序/筛选交互用refineCore暴露的分页状态配合usePagination渲染分页器。排序、筛选、分页全部以 CRUD 参数形式作用于数据源关联数据用useManytable meta优雅解决操作列与日期字段直接复用refinedev/chakra-ui的现成组件。理解适配器在 Core 与 TanStack Table 之间的同步机制后这套模式可以平滑迁移到 MUI、Mantine、Ant Design 等任意 UI 生态成为你构建管理后台列表页的通用范式。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进