Refine 数据获取进阶:useShow Hook 完整指南——从基础用法到源码级原理 📅 发布时间:2026/9/10 22:45:53 👁 浏览次数: Refine 数据获取进阶useShow Hook 完整指南——从基础用法到源码级原理【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refineuseShow是 Refinerefinedev/core中用于获取单条记录的核心数据 Hook它在useOne的基础之上扩展而来能够自动从当前 URL 中解析resource与id并调用 data provider 的getOne方法。本文以 useShow 官方文档为主体结合 useShow 源码实现 与 测试用例完整讲解其全部属性、返回值、实时更新机制与底层调用链帮助你写出可复用、可维护的记录详情页。useShow 是什么useShow是useOne的扩展版本支持useOne的全部特性并在此基础上增加了从 URL 自动推断资源与 id的能力。它的典型应用场景是「详情页 / Show 页面」当用户导航到/products/show/123这样的路由时useShow会自动读取路径中的resourceproducts与id123并作为参数传给 data provider 的getOne方法。从源码注释可以看到它的定位packages/core/src/hooks/show/index.tsuseShowhook allows you to fetch the desired record. It usesgetOnemethod as query function from the dataProvider that is passed toRefine.在 Refine v5 中useShow已经完成了从 v4 时代返回结构queryResult包裹data到扁平化返回结构result直接持有记录、query持有查询状态的演进这也是官方文档所展示的推荐用法。基础用法渲染一个产品详情页useShow默认不接收任何属性它会尝试从当前 URL 中读取resource和id。以下示例来自 官方基础用法 Live Preview演示了一个最小可用的产品详情页import { useShow } from refinedev/core; interface IProduct { id: number; name: string; material: string; } const ProductShow: React.FC () { const { result: product, query: { isFetching, isError, refetch }, } useShowIProduct(); if (isFetching) { return divLoading.../div; } if (isError) { return divSomething went wrong!/div; } return ( div h3Product Details/h3 pid: {product?.id}/p pname: {product?.name}/p pmaterial: {product?.material}/p button onClick{refetch}Refresh/button /div ); };配套的路由与资源声明如下live preview 中通过setRefineProps注入setRefineProps({ resources: [ { name: products, show: /products/show/:id, }, ], }); // 路由挂载 ReactRouter.Routes ReactRouter.Route path/products/show/:id element{ProductShow /} / /ReactRouter.Routes这个示例覆盖了useShow三个关键用法自动推断参数无需手动传入resource与idHook 从/products/show/123中解析出products与123扁平化返回值result直接就是记录对象product?.id而query是 TanStack Query 的查询结果可解构出isFetching、isError、refetch等状态与方法手动刷新通过query.refetch()重新触发getOne请求。如果你显式地在 Hook 上定义resource和id那么当这些属性发生变化时useShow会自动触发一次新的请求详见后文源码分析。属性Properties详解resourceresource用于指定要获取记录的资源名称默认从当前 URL 读取。手动指定时useShow({ resource: categories, });需要注意一旦手动传入resourceURL 中的id将被忽略——因为该id可能属于其他资源。此时应使用useParsed从 URL 中取出id再传入import { useShow, useParsed } from refinedev/core; const { id } useParsed(); useShow({ resource: custom-resource, id, });也可以不传id改用返回的setShowId函数在运行时设置import { useShow } from refinedev/core; const { setShowId } useShow({ resource: custom-resource, }); setShowId(123);当多个资源同名时可传入identifier而非资源name。identifier只作为资源匹配的主键data provider 的方法仍然使用Refine/组件中定义的资源name来调用参见 useShow 源码 中resource: identifier的传参方式。idid决定要获取哪一条记录会被作为参数传给 data provider 的getOne方法。默认从当前 URL 读取useShow({ id: 123, });从 类型定义 可以看到id的类型是BaseKey即string | number并支持泛型约束export type UseShowProps... { resource?: string; // default 从 URL 读取 :resource id?: BaseKey; // default 从 URL 读取 :id ... };metameta是一个特殊属性用于向 data provider 方法传递附加信息主要有两个用途针对特定用例定制 data provider 方法使用纯 JavaScript 对象JSON生成 GraphQL 查询。例如通过meta传递自定义请求头并在自定义 data provider 的getOne中消费它useShow({ meta: { headers: { x-meta-data: true }, }, }); const myDataProvider { //... getOne: async ({ resource, id, meta }) { const headers meta?.headers ?? {}; const url ${apiUrl}/${resource}/${id}; const { data } await httpClient.get(${url}, { headers }); return { data }; }, //... };从源码看useShow通过useMeta将资源定义resource definition、URL 查询参数与 Hook 传入的meta合并后再传给useOnepackages/core/src/hooks/show/index.ts。这一点在 测试用例 中得到了直接验证测试同时注入资源定义meta: { dip: dop }、URL 参数baz: qux与 Hook 参数foo: bar断言getOne最终收到的meta三者俱全。dataProviderName当项目中配置了多个 data provider 时用dataProviderName指定使用哪一个useShow({ dataProviderName: second-data-provider, });源码类型注释中明确其默认值为defaultpackages/core/src/hooks/show/types.ts该值最终会传给useOne用于通过useDataProvider解析出正确的 provider 实例。queryOptionsqueryOptions用于向底层的 TanStack QueryuseQuery透传额外选项useShow({ queryOptions: { retry: 3, enabled: false, }, });值得注意的底层细节useShow在内部会对queryOptions做一次合并且强制设置enabledpackages/core/src/hooks/show/index.tsconst queryResult useOneTQueryFnData, TError, TData({ resource: identifier, id: showId ?? , queryOptions: { enabled: showId ! undefined, ...queryOptions, }, ... });也就是说当showId尚未确定例如 URL 中没有 id、也未通过 prop 传入时查询会被禁用当showId被设置后查询自动启用。因此传入的queryOptions.enabled会覆盖这一默认行为需要谨慎使用。successNotification 与 errorNotification这两个属性需要NotificationProvider配合使用。数据获取成功/失败后useShow会调用NotificationProvider的open函数展示通知你可以用这两个属性自定义通知内容useShow({ successNotification: (data, values, resource) { return { message: ${data.title} Successfully fetched., description: Success with no errors, type: success, }; }, });useShow({ errorNotification: (data, values, resource) { return { message: Something went wrong when getting ${data.id}, description: Error, type: error, }; }, });从源码类型看UseShowProps混入了SuccessErrorNotificationGetOneResponseTData, TError, Prettify{ id?: BaseKey } MetaQuery类型packages/core/src/hooks/show/types.ts即通知回调的第二个参数values为{ id } meta的合并对象。实际通知触发逻辑由useOne内部的useHandleNotification完成。实时更新相关liveMode、onLiveEvent、liveParams以下三个属性均需要LiveProvider才能生效liveMode决定收到相关 live 事件时是自动auto还是手动manual更新数据用于在应用中实时更新并展示数据useShow({ liveMode: auto, });onLiveEvent订阅到新事件时的回调函数useShow({ onLiveEvent: (event) { console.log(event); }, });liveParams传给LiveProvider的subscribe方法的参数。在 Hook 挂载时useShow经由useOne内部的useResourceSubscription会以channel、resource等参数调用liveProvider.subscribe从而订阅实时更新卸载时相应取消订阅。这些 live 相关 props 通过...useOneProps透传packages/core/src/hooks/show/index.ts。overtimeOptions用于处理请求耗时过长的场景interval为回调间隔毫秒数onInterval为每个间隔触发的函数。配合返回值中的overtime对象elapsedTime为已耗时的毫秒数请求完成后变为undefinedconst { overtime } useShow({ //... overtimeOptions: { interval: 1000, onInterval(elapsedInterval) { console.log(elapsedInterval); }, }, }); console.log(overtime.elapsedTime); // undefined, 1000, 2000, 3000 4000, ... // 典型用法超时提示 { overtime.elapsedTime 4000 divthis takes a bit longer than expected/div; }底层由useLoadingOvertimeHook 实现useShow将其返回的overtime原样透出packages/core/src/hooks/show/types.ts 中UseShowReturnType与UseLoadingOvertimeReturnType交叉。返回值Return Values属性说明queryTanStack QueryuseQuery的完整返回值QueryObserverResult{ data: TData; error: TError }包含isFetching、isError、refetch、isSuccess、data等result解构后的记录数据TData为query.data?.data的便捷别名undefined表示尚未获取成功showId当前useShow正在使用的id值setShowIdshowId的 setter类型为DispatchSetStateActionBaseKey \| undefined调用后会触发一次新的数据请求overtime超时加载信息{ elapsedTime?: number }从 类型定义 可以确认query与result的关系export type UseShowReturnTypeTData, TError { query: QueryObserverResultGetOneResponseTData, TError; result: TData | undefined; showId?: BaseKey; setShowId: React.DispatchReact.SetStateActionBaseKey | undefined; } UseLoadingOvertimeReturnType;setShowId的典型场景是基于用户交互切换详情对象例如列表点击、轮播切换等源码实现中将setShowId直接指向useResourceParams返回的setIdconst { resource, identifier, id: showId, setId: setShowId, } useResourceParams({ id, resource: resourceFromProp });实时更新Realtime Updates当useShow挂载时它会调用liveProvider的subscribe方法并传入channel、resource等参数这样当该记录在服务端发生变化时客户端可以收到实时事件并更新界面。结合liveMode: auto即可实现「无需刷新页面数据自动更新」的体验。完整的 LiveProvider 配置与liveMode语义参见 Live / Realtime 文档。源码级实现useShow 的完整调用链从 packages/core/src/hooks/show/index.ts 的完整实现可以看到useShow的四个核心步骤解析资源与 id调用useResourceParams({ id, resource: resourceFromProp })从 URL 或 props 中解析出resource、identifier、id即showId与setId即setShowId。这是「从 URL 自动推断」能力的来源合并 meta调用useMeta()生成getMeta把资源定义、URL 参数与 Hook 传入的meta合并为combinedMeta兜底告警当显式传入resource但showId缺失时通过warnOnce输出一条警告提示用户应使用setShowId或显式传入id否则useShow无法从 URL 推断 id警告信息源码委托给 useOneuseShow本身不直接调用useQuery而是把解析结果与全部透传属性交给useOne由useOne完成真正的查询通过useDataProvider按dataProviderName解析 data provider 实例调用 data provider 的getOne作为查询函数通过useResourceSubscription完成实时订阅通过useHandleNotification触发成功/失败通知通过useLoadingOvertime实现超时检测最终基于 TanStack Query 的useQuery返回QueryObserverResult。这也是为什么文档将其定义为「useOne的扩展版本」所有useOne的能力meta、dataProviderName、通知、实时、超时在useShow中都被完整保留useShow额外提供的只是 URL 推断与showId状态管理。测试验证行为如何被保证packages/core/src/hooks/show/index.spec.tsx 中的测试用例直接印证了上述行为从 URL 读取 id使用mockRouterProvider({ action: show, id: 1, pathname: /posts/show/1 })直接调用useShow()即可成功获取posts[0]且showId 1对应测试 correctly return id value from route从 props 读取参数useShow({ resource: posts, id: 1 })与useShow({ resource: categories, id: 2 })均能正确返回对应的showId与数据资源与路由不一致时的行为当路由是/posts/show/1却传入resource: categories不带 id时showId为undefinedURL 中的 id 被忽略印证了文档中「显式传入 resource 会忽略 URL id」的约定setShowId 动态切换先断言默认showId 1再调用result.current.setShowId(3)断言showId更新为3且更新 prop 会触发重新请求meta 合并断言资源定义、URL 查询参数与 Hook 参数的 meta 会一并传递给getOne。API 参考Propsresource?: string——资源名称默认读取 URL 中的:resourceid?: BaseKey——记录 id默认读取 URL 中的:idqueryOptions?: MakeOptionalUseQueryOptions..., queryKey | queryFn——TanStack QueryuseQuery选项meta?: MetaQuery——传给 data providergetOne的附加元数据dataProviderName?: string——目标 data provider 名称默认defaultsuccessNotification/errorNotification——自定义成功/失败通知需NotificationProviderliveMode?: auto | manual | off——实时更新模式默认offonLiveEvent?: (event) void——实时事件回调liveParams?: LiveParams——传给liveProvider.subscribe的参数overtimeOptions?: { interval: number; onInterval?: (elapsedInterval) void }——超时检测选项。类型参数Type Parameters属性说明类型默认值TQueryFnData查询函数返回的数据类型需继承BaseRecordBaseRecordBaseRecordTError自定义错误对象需继承HttpErrorHttpErrorHttpErrorTDataselect函数返回的数据类型需继承BaseRecord未指定时默认取TQueryFnDataBaseRecordTQueryFnData返回值属性说明类型query单条记录查询的结果QueryObserverResult{ data: TData; error: TError }result记录数据TData \| undefinedshowId记录 idBaseKeysetShowIdshowId的 setterDispatchSetStateActionBaseKey \| undefinedovertime超时加载信息{ elapsedTime?: number }小结useShow是 Refine 中编写详情页的推荐入口它继承useOne的全部数据获取能力getOne、meta 合并、多 provider、通知、实时订阅、超时检测并在此基础上通过useResourceParams实现 URL 参数自动推断与showId状态管理。理解其「委托useOne 扁平化返回」的实现方式有助于你在自定义详情页、跨资源展示和实时场景中写出更精准的代码。更多相关概念可继续阅读 useOne 文档 与 LiveProvider 文档。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考