ARTICLE DETAIL

资讯详情

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

refine 中 useList 分页(pagination)完全指南:currentPage、pageSize 与 client / server / off 三种模式

refine 中 useList 分页(pagination)完全指南:currentPage、pageSize 与 client / server / off 三种模式 refine 中 useList 分页pagination完全指南currentPage、pageSize 与 client / server / off 三种模式【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refineuseList是 refine 基于 TanStack Query 的useQuery封装的列表数据获取 Hook用于按分页、排序、过滤条件从resource拉取数据。本篇围绕 documentation/docs/data/hooks/use-list/index.md 中分页章节及其分页示例展开结合 packages/core/src/hooks/data/useList.ts 源码与单测讲透分页参数的默认值、三种mode的底层行为差异以及如何构建可用的上一页 / 下一页 / 每页条数切换控件。useList 与分页数据从哪来useList的定位是 TanStack QueryuseQuery的扩展版本支持其全部能力并额外增加了分页、排序、过滤、实时订阅、通知等 refine 特性。在分页场景下它的工作链路非常清晰useList使用dataProvider的getList方法作为查询函数query function将pagination、sorters、filters等参数透传给后端useList根据传入属性生成 query key 并缓存数据动态修改pagination属性会生成新的 query key从而自动触发新的请求。从源码 useList.ts 可以看到queryFn最终调用的是getListqueryFn: (context) { const meta { ...combinedMeta, ...prepareQueryContext(context), }; return getListTQueryFnData({ resource: resource?.name ?? , pagination: prefferedPagination, filters: prefferedFilters, sorters: prefferedSorters, meta, }); },也就是说你传给useList的分页配置最终会原样经过默认值补齐后进入getList由你的 data provider 决定如何把它转换成 API 的?page2pageSize5之类的查询参数。分页参数currentPage、pageSize 与 modepagination属性接受一个对象包含三个可选字段定义见 packages/core/src/contexts/data/types.tsmode?: client | server | off参数类型说明currentPagenumber当前页码从 1 开始pageSizenumber每页条数modeoff \| client \| server分页模式决定是否使用服务端分页三个字段都不是必填的。缺省时的行为由 packages/core/src/definitions/helpers/handlePaginationParams/index.ts 统一处理export const handlePaginationParams ({ pagination, }: HandlePaginationParamsProps {}): RequiredPagination { const mode pagination?.mode ?? server; const currentPage pagination?.currentPage ?? 1; const pageSize pagination?.pageSize ?? 10; return { currentPage, pageSize, mode }; };默认值分别是mode缺省为servercurrentPage缺省为1pageSize缺省为10。这些默认值同样被 handlePaginationParams/index.spec.ts 的测试用例锁定expect(handlePaginationParams()).toEqual({ currentPage: 1, pageSize: 10, mode: server })。因此即使你只写useList({ resource: products })内部也会以{ currentPage: 1, pageSize: 10, mode: server }的标准形态向getList发起请求。三种 mode 的底层差异mode是理解分页行为的关键三种取值的差异可以直接在 useList.ts 中找到对应实现server默认服务端分页isServerPagination为true分页参数会进入 query key见 useList.ts#L249-L251页码或每页条数变化即产生新 key、触发新请求getList收到完整的pagination参数由后端完成切片前端只负责渲染返回的当前页数据。useList({ resource: products, pagination: { currentPage: 2, pageSize: 20, }, });client客户端分页后端仍然一次性返回全部数据useList在内存中完成切片。对应实现是memoizedSelect见 useList.ts#L212-L222if (prefferedPagination.mode client) { data { ...data, data: data.data.slice( (prefferedPagination.currentPage - 1) * prefferedPagination.pageSize, prefferedPagination.currentPage * prefferedPagination.pageSize, ), total: data.total, }; }切片区间为[(currentPage - 1) * pageSize, currentPage * pageSize)这正是标准的从零偏移计算方式由于切片发生在select阶段切换页码不会重新请求后端适合数据量可控、希望减轻服务端压力的场景。off关闭分页关闭分页语义isServerPagination为false分页参数不进入 query keyselect也不会切片后端应一次性返回全部数据。从源码看mode是否为server直接决定了分页参数是否参与缓存 key 的生成这也是动态修改pagination会触发新请求这一行为的底层原因。完整实战带页码与每页条数控件的产品列表原文档的分页示例见 documentation/docs/data/hooks/use-list/_pagination-live-preview.md演示了最典型的服务端分页交互用两个按钮控制currentPage用一个下拉框控制pageSize并把状态通过pagination属性传给useList。下面是完整可运行的版本相比原示例补充了边界控制与总行数展示import { useState } from react; import { useList, HttpError } from refinedev/core; interface IProduct { id: number; name: string; material: string; } const ProductList: React.FC () { const [currentPage, setCurrentPage] useState(1); const [pageSize, setPageSize] useState(5); const { result, query } useListIProduct, HttpError({ resource: products, pagination: { currentPage, pageSize, }, }); const products result.data ?? []; const total result.total; if (query.isLoading) { return divLoading.../div; } if (query.isError) { return divSomething went wrong!/div; } return ( div button onClick{() setCurrentPage((prev) Math.max(1, prev - 1))} disabled{currentPage 1} {} /button span page: {currentPage} /span button onClick{() setCurrentPage((prev) prev 1)}{}/button span per page: /span select value{pageSize} onChange{(e) { setPageSize(Number(e.target.value)); // 切换每页条数后回到第一页避免停留在越界页码 setCurrentPage(1); }} {[5, 10, 20].map((size) ( option key{size} value{size} {size} /option ))} /select p total: {total} · showing {products.length} items /p ul {products.map((product) ( li key{product.id} h4 {product.name} - ({product.material}) /h4 /li ))} /ul /div ); };要点说明currentPage与pageSize由useState管理传入pagination后任何一处变化都会在server模式下触发新的数据请求通过result.data取当前页数据、result.total取总条数空数据时用?? []兜底用query.isLoading/query.isError处理加载与错误状态切换pageSize时建议同时把页码重置为 1避免用户停在超出总页数的位置示例依赖setInitialRoutes([/products])与resources配置name: products, list: /products在真实项目中即为Refine组件里注册的products资源。总行数rowCount / total是怎么来的分页 UI 往往需要展示总共有多少条useList调用getList时期望响应中包含总行数。获取方式因 data provider 而异见 documentation/docs/data/hooks/use-list/index.mdREST 类 Provider常通过响应头x-total-count获取总条数GraphQL 类 Provider通常在数据字段中返回例如pageInfo.total其他 Provider遵循各自的约定。如果后端没有提供明确的总数getList可能默认使用返回数据数组的长度作为rowCount。这意味着当你的接口不支持返回总数时result.total反映的是本页条数而非真实总量需要在后端补齐计数或自行处理。返回值query 与 resultuseList的返回类型定义在 useList.ts#L97-L104export type UseListReturnTypeTData, TError { query: QueryObserverResultGetListResponseTData, TError; result: { data: TData[]; total: number | undefined; [key: string]: any; }; } UseLoadingOvertimeReturnType;queryTanStack QueryuseQuery的完整返回对象包含isLoading、isError、isFetching、refetch等result解构后的便捷形态data为当前页数据数组无数据时返回空数组total为总条数额外的overtime对象配合overtimeOptions使用可用于请求超时提示。分页相关配置通过queryOptions还能进一步控制查询行为例如useList({ resource: products, pagination: { currentPage, pageSize }, queryOptions: { retry: 3, // 失败重试次数 enabled: !!id, // 条件启停 }, });与其他数据能力组合使用分页通常与排序、过滤同时出现它们共享同一套透传机制排序sorters属性传给getList示例见 documentation/docs/data/hooks/use-list/_sorting-live-preview.md过滤filters属性传给getList示例见 documentation/docs/data/hooks/use-list/_filtering-live-preview.md。在 useList.ts 的 query key 生成逻辑中filters、pagination服务端模式、sorters都被纳入 key 的params部分因此三者任一变化都会触发重新请求且彼此共享缓存、互不干扰。小结useList把分页参数透传给 data provider 的getList缺省值为{ currentPage: 1, pageSize: 10, mode: server }由 handlePaginationParams 统一补齐并有单测保障mode: server走服务端分页参数进入 query key切换即重新请求mode: client由select在内存切片mode: off关闭分页页面控件只需维护currentPage/pageSize两个状态并传入pagination即可获得完整的上一页 / 下一页 / 每页条数切换能力展示总条数依赖result.total其来源响应头、GraphQL 字段或数据长度兜底由 data provider 决定。如果需要深入getList如何把这些参数转换成实际 API 请求可以继续阅读仓库中 data provider 的getList实现及对应文档。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表