尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Refine 的 useCustom Hook 完全指南:自定义查询、配置参数与实现原理

Refine 的 useCustom Hook 完全指南:自定义查询、配置参数与实现原理 Refine 的 useCustom Hook 完全指南自定义查询、配置参数与实现原理【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refineuseCustom是 Refine v5 中用于发送自定义查询请求的数据 Hook它基于 TanStack Query 的useQuery扩展而来将url、method、config等参数透传给数据提供者dataProvider的custom方法。本文以仓库内官方文档与源码为依据系统讲解useCustom的全部属性、返回值与底层实现机制帮助你对接自定义 API 端点、执行唯一性校验、调用报表接口等无法用标准 CRUD Hook 覆盖的场景并掌握查询失效invalidate与超时提示的正确姿势。useCustom 是什么useCustom是 Refine 中面向“自定义请求”的查询 Hook。它本质上是 TanStack QueryuseQuery的扩展版本不仅完整继承useQuery的全部能力缓存、重试、轮询、select转换等还额外提供了 Refine 生态特有的能力——通知NotificationProvider、鉴权错误回调onError、meta 合并、加载超时overtime等。从源码可以看到它的核心职责见 packages/core/src/hooks/data/useCustom.tsif (custom) { const queryResponse useQuery...({ queryKey: keys() .data(dataProviderName) .mutation(custom) .params({ method, url, ...config, ...(preferredMeta || {}) }) .get(), queryFn: (context) customTQueryFnData({ url, method, ...config, meta: { ...combinedMeta, ...prepareQueryContext(context as any) }, }), ...queryOptions, }); }也就是说useCustom的查询函数queryFn就是 dataProvider 上的custom方法。只要在传给Refine的 dataProvider 上实现了customuseCustom就能正常工作如果 dataProvider 没有实现customHook 会直接抛出错误Not implemented custom on data provider.这一点在测试用例 packages/core/src/hooks/data/useCustom.spec.tsx 中有明确验证。何时不该使用 useCustom:::caution 使用场景警告useCustom不应用于资源的增、删、改操作。创建、更新、删除请分别使用 useCreate、useUpdate、useDelete。 :::原因在于useCustom与其他数据 Hook 不同它不会自动失效invalidate相关查询因此也不会主动刷新应用状态。如果你需要自定义的是“变更类”请求请改用 useCustomMutation Hook。基本用法useCustom要求必传url和method两个属性它们会作为参数传给 dataProvider 的custom方法当这些属性发生变化时Hook 会触发一次新的请求得益于 TanStack Query 的 queryKey 机制。典型用法如下先通过useApiUrl拿到当前 dataProvider 的 API 基础地址再拼接自定义端点import { useCustom, useApiUrl } from refinedev/core; interface PostUniqueCheckResponse { isAvailable: boolean; } const apiUrl useApiUrl(); const { query } useCustomPostUniqueCheckResponse({ url: ${apiUrl}/posts-unique-check, method: get, config: { headers: { x-custom-header: foo-bar, }, }, });useApiUrl内部会读取当前资源对应的 dataProvider可通过参数指定名称并调用其getApiUrl方法返回基础 URL见 packages/core/src/hooks/data/useApiUrl.ts。Properties 详解url必填url会被直接传给 dataProvider 的custom方法通常用于指定请求的端点地址useCustom({ url: www.example.com/api/get-products, });method必填method指定 HTTP 方法。在源码中method的类型被严格限制为以下七种之一见 packages/core/src/hooks/data/useCustom.tsmethod: get | delete | head | options | post | put | patch;useCustom({ method: get, });config.headers用于指定请求头会原样透传给custom方法useCustom({ config: { headers: { x-custom-header: foo-bar, }, }, });config.query用于指定查询参数query stringuseCustom({ config: { query: { title: Foo bar, }, }, });config.payload用于指定请求体body。例如调用post或put类自定义端点时携带数据useCustom({ config: { payload: { title: Foo bar, }, }, });config.sorters用于发送排序参数字段结构与getList的排序一致useCustom({ config: { sorters: [ { field: title, order: asc, }, ], }, });config.filters用于发送过滤参数支持 Refine 的条件运算符如containsuseCustom({ config: { filters: [ { field: title, operator: contains, value: Foo, }, ], }, });在源码中config的完整类型为UseCustomConfig包含sorters、filters、query、payload、headers五个可选字段见 packages/core/src/hooks/data/useCustom.ts。queryOptionsqueryOptions用于向底层的useQuery透传额外选项例如调整重试次数、禁用自动请求等。它与 TanStack QueryuseQuery的选项保持一致useCustom({ queryOptions: { retry: 3, enabled: false, }, });注意一个细节Refine 在内部已经为你生成了 queryKey因此queryOptions中的queryKey与queryFn在类型上被设计为可选以便向后兼容见 packages/core/src/hooks/data/useCustom.ts。当你主动传入queryKey时它会覆盖默认的自动生成的 key——这一点在测试用例“with custom query key”中有验证见 packages/core/src/hooks/data/useCustom.spec.tsx。metameta是一个特殊属性用于向 dataProvider 方法传递额外信息常见用途有针对特定用例定制 dataProvider 方法的行为用纯 JavaScript 对象JSON生成 GraphQL 查询。在下面的示例中meta作为参数传入 dataProvider 的custom方法useCustom({ meta: { foo: bar, }, }); const myDataProvider { //... custom: async ({ url, method, sort, filters, payload, query, headers, meta, }) { const foo meta?.foo; console.log(foo); // bar //... }, //... };从实现上看meta还会与当前路由参数、资源级 meta 合并源码中通过getMeta合并显式传入的meta与资源上下文 meta并在 queryFn 里与 TanStack Query 的查询上下文一起传给custom见 packages/core/src/hooks/data/useCustom.ts。测试用例验证了meta会与路由参数baz: qux合并后传给custom方法见 packages/core/src/hooks/data/useCustom.spec.tsx。dataProviderName当应用配置了多个 dataProvider 时用dataProviderName指定本次请求使用哪一个useCustom({ dataProviderName: second-data-provider, });successNotification成功通知定制。需要先配置 NotificationProvider此属性才生效。请求成功且useCustom调用 NotificationProvider 的open函数时会使用这里返回的配置useCustom({ successNotification: (data, values) { return { message: ${data.title} Successfully fetched., description: Success with no errors, type: success, }; }, });源码中成功通知的处理逻辑位于 packages/core/src/hooks/data/useCustom.ts当queryResponse.isSuccess且存在数据时如果successNotification是函数则以数据、合并后的 config 与 meta为参数调用它返回false则可静默跳过通知测试用例“should not call open from notification provider on return false”验证了这一点。errorNotification失败通知定制同样依赖 NotificationProvideruseCustom({ errorNotification: (data, values) { return { message: Something went wrong when getting ${data.id}, description: Error, type: error, }; }, });需要留意的是即使你没有传errorNotificationRefine 仍会为失败请求弹出一条默认错误通知key 为${method}-notification例如get-notificationmessage 为Error (status code: ...)相关逻辑见 packages/core/src/hooks/data/useCustom.ts。测试用例 packages/core/src/hooks/data/useCustom.spec.tsx 也断言了默认错误通知的内容。overtimeOptions用于请求加载超时的场景——当请求耗时过长时展示加载提示。interval是时间间隔毫秒onInterval会在每个间隔触发一次const { overtime } useCustom({ //... overtimeOptions: { interval: 1000, onInterval(elapsedInterval) { console.log(elapsedInterval); }, }, }); console.log(overtime.elapsedTime); // undefined, 1000, 2000, 3000 4000, ... // You can use it like this: { elapsedTime 4000 divthis takes a bit longer than expected/div; }返回的overtime.elapsedTime表示已耗时毫秒请求完成时变为undefined。测试用例验证了interval与onInterval的行为请求挂起期间elapsedTime持续累加请求完成后重置为undefined见 packages/core/src/hooks/data/useCustom.spec.tsx。返回值useCustom返回一个对象源码定义见 packages/core/src/hooks/data/useCustom.ts名称说明类型queryTanStack Query 的查询结果对象QueryObserverResultCustomResponseTData, TErrorresult便捷取数对象result.data即响应数据{ data: CustomResponseTData[data] }overtime加载超时信息{ elapsedTime?: number }{ elapsedTime?: number }其中CustomResponse的定义为{ data: TData }见 packages/core/src/contexts/data/types.ts。因此你可以用query.data?.data或result.data两种方式读取真正的响应数据。类型参数Type Parameters属性说明类型默认值TQueryFnData查询函数返回的数据类型继承自BaseRecordBaseRecordBaseRecordTError自定义错误对象继承自HttpErrorHttpErrorHttpErrorTQuery查询参数的类型TQueryunknownTPayload请求体参数的类型TPayloadunknownTDataselect函数返回的数据类型继承自BaseRecord未指定时默认取TQueryFnDataBaseRecordTQueryFnData说明BaseRecord与HttpError均为 Refine 核心接口定义可参考 packages/core/src/contexts/data/types.ts。源码视角useCustom 的底层执行链路结合源码与测试可以梳理出useCustom的完整执行链路取 dataProvider通过useDataProvider按dataProviderName缺省为当前资源关联的 provider解析出 provider并取出其custom方法生成 queryKeyRefine 使用keys().data(dataProviderName).mutation(custom).params({ method, url, ...config, ...meta }).get()自动构建稳定的查询键——这意味着只要url、method、config或meta变化queryKey 就会变化并触发重新请求执行查询queryFn 调用custom并额外传入合并了 meta 与查询上下文的信息通知与鉴权成功时触发成功通知失败时先调用鉴权提供者的onError/checkError处理401 等场景再触发错误通知超时跟踪通过useLoadingOvertime基于queryResponse.isFetching驱动overtime.elapsedTime无 custom 时抛错如果 dataProvider 未实现custom抛出Not implemented custom on data provider.。与之对应的参数契约是CustomParams见 packages/core/src/contexts/data/types.ts它定义了url、method、sorters?、filters?、payload?、query?、headers?、meta?等字段这也是实现自定义 dataProvider 时custom方法的标准入参。真实数据提供者如何实现 custom以 simple-rest 为例以仓库内置的refinedev/simple-rest为例其custom实现见 packages/simple-rest/src/provider.ts展示了sorters、filters、query如何被拼接为查询字符串排序会转换为_sort/_order参数过滤会通过generateFilter生成查询串query直接 stringify 追加到 URL随后按method分发到 axios 请求。这解释了useCustom传入的config在真实 REST 场景下的落点——你可以基于此模式编写自己的custom实现也可以直接使用 simple-rest 获得开箱即用的自定义请求支持。FAQ如何使自定义查询失效invalidate由于useCustom不会自动失效查询当你需要主动刷新数据例如某个自定义查询的依赖数据被更新后时可以使用 TanStack Query 的useQueryClient提供的invalidateQueries方法import { useQueryClient } from tanstack/react-query; const queryClient useQueryClient(); queryClient.invalidateQueries([custom-key]);请注意你需要知道该查询的 queryKey才能使其失效。如果你不清楚默认生成的 key可以通过queryOptions.queryKey为useCustom显式指定一个稳定的 keyimport { useCustom } from refinedev/core; useCustom({ queryOptions: { queryKey: [custom-key], }, });之后无论何时调用invalidateQueries([custom-key])都能精准命中并刷新该自定义查询。小结useCustom是 Refine 中对接自定义端点的首选查询 Hook完整继承 TanStack QueryuseQuery的能力并叠加 Refine 的通知、鉴权、meta 与超时机制。全部请求参数通过url、method、configheaders/query/payload/sorters/filters与meta传递给 dataProvider 的custom方法参数变化会自动触发重新请求。增删改场景请使用useCreate/useUpdate/useDelete需要自定义变更请求时使用useCustomMutation。手动刷新自定义查询时通过queryOptions.queryKey固定 key再配合queryClient.invalidateQueries精准失效。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表