Refine v3 useList 排序实战:通过 config.sort 动态触发服务端排序请求
2026/9/14 16:37:28 网站建设 项目流程

Refine v3 useList 排序实战:通过 config.sort 动态触发服务端排序请求

【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine

Refine v3 的数据 HookuseList是 TanStack QueryuseQuery的扩展,负责从指定resource拉取列表数据,并将分页、排序、过滤等配置透传给dataProvidergetList方法。本文以 v3 官方文档中useList的排序(Sorting)Live Preview 为例,完整讲解config.sort的用法、"排序参数变化自动触发新请求"的机制,并结合开源仓库中useList的源码实现说明其底层原理与参数流转路径。读完本文,你将能够:在任意 Refine 页面中实现可切换升/降序的列表、理解排序参数如何进入查询缓存键并驱动重新请求、以及掌握useList各配置项的完整参数表。

一、排序示例完整代码

排序是useList的核心能力之一。下面这段代码完整来自仓库中的排序 Live Preview 演示文件 sorting-live-preview.md,它展示了一个可点击切换升/降序的产品列表组件:

import { useState } from "react"; import { useList, HttpError } from "@pankod/refine-core"; interface IProduct { id: number; name: string; material: string; } const ProductList: React.FC = () => { const [order, setOrder] = useState<"asc" | "desc">("asc"); const { data, isLoading, isError } = useList<IProduct, HttpError>({ resource: "products", config: { sort: [ { field: "name", order, }, ], }, }); const products = data?.data ?? []; if (isLoading) { return <div>Loading...</div>; } if (isError) { return <div>Something went wrong!</div>; } return ( <div> <button onClick={() => setOrder((prev) => (prev === "asc" ? "desc" : "asc")) } > toggle sort </button> <ul> {products.map((product) => ( <li key={product.id}> <h4> {product.name} - ({product.material}) </h4> </li> ))} </ul> </div> ); };

演示文件同时将该组件注册为products资源的list页面并渲染 Headless 版<Refine>骨架:

setRefineProps({ resources: [ { name: "products", list: ProductList, }, ], }); render(<RefineHeadlessDemo />);

代码要点拆解:

  1. useState持有排序方向order的取值只能是"asc" | "desc"字面量联合,与sort配置项中order字段的类型严格一致。
  2. sort是数组结构config.sort接收Array<{ field: string; order: "asc" | "desc" }>,数组顺序即多字段排序的优先级,上面的示例按name字段单字段排序。
  3. 排序方向是响应式的:点击toggle sort按钮更新order状态后,useList收到新的sort参数,自动发起一次新的getList请求。

二、useList的排序工作机制

排序部分在 v3 官方文档 useList/index.md 中的原始描述是:useList支持排序特性,传入sort属性即可启用排序;useList会将sort属性透传给dataProvidergetList方法处理;动态修改sort属性会触发一次新请求

这句话背后有两条机制在支撑:

1. 查询键(Query Key)由参数生成,参数变了缓存键就变

文档明确说明:useList使用一个由传入属性生成的 query key 来缓存数据,可以通过 TanStack Query devtools 查看该 key。从当前仓库packages/coreuseList的源码结构可以印证这一机制:查询键由dataProviderName + resource + action("list") + params逐段构建,其中 params 包含了 filters、pagination、sorters 等参数(见 useList.ts)。由于排序参数是缓存键的组成部分,order"asc"变为"desc"时缓存键随之改变,TanStack Query 判定为"新查询",从而自动重新执行查询函数——这就是示例中"点按钮即刷新列表"的底层原因,无需手动调用 refetch。

2.queryFn将排序参数原样交给dataProvider.getList

查询函数的实现就是把resourcepaginationfilters、排序参数与meta一起传给getList(见 useList.ts)。具体排序参数如何转成 URL query string(例如?sort=name&order=asc),完全取决于所用dataProvider的实现——resource通常被当作 API 端点路径,处理方式"完全取决于getList方法内部对resource的处理逻辑"(文档原话)。仓库中@refinedev/rest包内置了 nestjsx-crud、simple-rest、strapi-v4 等多种 provider,各自的options文件定义了排序参数的默认转换策略(如 nestjsx-crud.options.ts),并提供 handleSort 等工具函数及对应测试(handleSort.spec.ts),可以按 provider 逐一查看排序参数的落地格式。

三、config参数完整说明(v3 API)

v3 文档在 "Config Parameters" 一节给出了UseListConfig的完整接口定义,这是使用useList时最重要的参考契约:

interface UseListConfig { hasPagination?: boolean; pagination?: { current?: number; pageSize?: number; }; sort?: Array<{ field: string; order: "asc" | "desc"; }>; filters?: Array<{ field: string; operator: CrudOperators; value: any; }>; }

各配置项的用途:

配置项说明示例
config.sort排序参数,透传给getList,用于向 API 发送排序 query 参数sort: [{ field: "title", order: "asc" }]
config.filters过滤参数,向 API 发送过滤 query 参数,遵循CrudFilters接口filters: [{ field: "title", operator: "contains", value: "Foo" }]
config.pagination.current当前页码pagination: { current: 2 }
config.pagination.pageSize每页条数pagination: { pageSize: 20 }
config.hasPagination是否启用服务端分页(不启用则一次性取回数据)hasPagination: false

三个参数(sortfilterspagination)遵循同一套响应式规则:动态修改任意一个都会触发新的getList请求,因为它们是查询缓存键的组成部分。

useListconfig外还支持以下顶层属性(均为可选):

属性说明示例
resource(必填)资源名,透传给getList,通常被用作 API 端点路径resource: "categories"
dataProviderName存在多个 dataProvider 时指定使用哪一个dataProviderName: "second-data-provider"
queryOptions透传给useQuery的额外选项queryOptions: { retry: 3 }
metaData向 dataProvider 方法传递附加信息(如请求头),或用于以普通 JS 对象生成 GraphQL 查询metaData: { headers: { "x-meta-data": "true" } }
successNotification需要NotificationProvider;数据拉取成功后调用其open展示成功通知,可自定义返回{ message, description, type }见下方示例
errorNotification需要NotificationProvider;拉取失败时展示错误通知,可自定义见下方示例
liveMode需要LiveProvider;取"auto""manual",决定收到实时事件时是否自动更新数据liveMode: "auto"
onLiveEvent需要LiveProvider;订阅事件到达时的回调onLiveEvent: (event) => console.log(event)
liveParams需要LiveProvider;透传给liveProvider.subscribe的参数

通知回调示例:

useList({ successNotification: (data, values, resource) => { return { message: `${data.title} Successfully fetched.`, description: "Success with no errors", type: "success", }; }, });

四、类型参数与返回值

类型参数(v3 API):

类型参数说明类型默认值
TData查询结果数据类型,继承BaseRecordBaseRecordBaseRecord
TError自定义错误对象类型,继承HttpErrorHttpErrorHttpError

TData即示例中useList<IProduct, HttpError>的第一个参数,用来让data.data获得IProduct[]这样的精确类型推导。

返回值useList直接返回 TanStack QueryuseQueryQueryObserverResult<{ data: TData[]; total: number }, TError>,因此dataisLoadingisErrorrefetch等标准字段都可直接使用,示例中取data?.data得到记录数组、data?.total得到总数(服务端分页场景下)。

五、版本演进提示:v3 到当前 main 分支的 API 差异

需要注意本文代码与参数表对应的是v3 版本 API(包名@pankod/refine-core,文档路径位于 version-3.xx.xx)。当前仓库packages/core的主干源码已是后续大版本的实现,从源码结构看有两处明显的 API 演进:

  1. sort更名为sorters:主分支的UseListProps中参数名为sorters?: CrudSort[],且不再是config的子字段,而是与filterspagination平级的顶层参数(见 useList.ts)。同理metaData对应为meta
  2. 返回值结构变化:主分支useList不再直接平铺useQuery结果,而是返回{ query, result, overtime }结构,其中result.data为记录数组(内部用EMPTY_ARRAY兜底空数据)、result.total为总数,query保留完整的useQuery返回值(见 useList.ts 与 useList.ts)。

如果你正在使用 v3 项目,请以本文的config.sort写法为准;若阅读主分支源码或测试(useList.spec.tsx)时看到sorters,两者语义一致,只是命名与层级调整。排序"参数变化即触发新请求"的核心机制——参数参与 query key 生成、queryFn透传给getList——在两个版本中保持一致。

六、小结

  • useList的排序通过config.sort: [{ field, order }]声明,order仅支持"asc" | "desc",数组顺序决定多字段排序优先级;
  • 排序参数是查询缓存键的组成部分,用useState动态修改order即可让 TanStack Query 自动发起新的getList请求,无需手动 refetch;
  • 排序参数如何落地为 URL query 参数由各dataProvidergetList实现决定,@refinedev/rest内置 provider 提供了可查阅的默认转换实现与测试;
  • useList同时支持过滤、分页、metaData 透传、成功/失败通知与实时订阅等配置,类型参数TData/TErroruseQuery返回值保证了完整的类型推导能力。

【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询