Refine useShow Hook 完全指南从 URL 智能取值到实时更新的单记录数据获取方案【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refineuseShow是 Refine 数据获取体系中用于展示单条记录的核心 Hook它是useOne的超集版本既完整继承了useOne的全部能力又额外提供了基于当前 URL 自动推断resource与id、以及setShowId动态切换记录等增强特性。本文基于 Refine 官方文档与仓库源码从基础用法、全部 Props 配置、返回值到源码级实现原理逐一展开帮助你彻底掌握在管理后台「详情页」场景中高效、健壮地获取和展示单条数据。useShow 是什么与 useOne 的关系useShow是 Refine 提供的用于从 API 获取单条记录single record的 Hook官方定位为useOne的扩展版本——它支持useOne的所有特性并在此基础上增加了一些能力。从源码可以清晰看到这一关系useShow实现 内部直接调用了useOne并通过useResourceParams解析出resource、identifier、id即showId与setId再把这些值透传给useOneconst queryResult useOneTQueryFnData, TError, TData({ resource: identifier, id: showId ?? , queryOptions: { enabled: showId ! undefined, ...queryOptions, }, meta: combinedMeta, overtimeOptions, ...useOneProps, });而useOne本身又是 TanStack QueryuseQuery的封装版本使用 dataProvider 的getOne方法作为查询函数。因此调用链可以概括为useShow → useResourceParams解析 URL / Props→ useOne → useQuery dataProvider.getOne关于useOne的详细说明可参考useOne文档 及其源码 useOne.ts。基本用法零参数调用自动读取 URLuseShow最显著的使用特点是不需要传入任何属性。默认情况下它会尝试从当前 URL 中读取resource和id值并将其作为参数传递给 dataProvider 的getOne方法。当你在useShow上显式定义了resource和id时一旦这些属性发生变化useShow就会触发一次新的请求。以下是一个典型的「商品详情页」示例来自文档的内联实时预览 _basic-usage-live-preview.mdimport { 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 ); };其中路由配置形如setRefineProps({ resources: [ { name: products, show: /products/show/:id, }, ], });这里的useShowIProduct()没有传任何参数完全依赖路由/products/show/123解析出的resource: products与id: 123。result是解构后的数据本体query则是 TanStack Query 的查询结果对象可以直接使用isFetching、isError、refetch等控制项。源码中的默认行为验证在 useShow 源码 中useResourceParams负责这一解析逻辑const { resource, identifier, id: showId, setId: setShowId, } useResourceParams({ id, resource: resourceFromProp, });同时源码还通过warnOnce在「显式传入了resource但当前没有showId」时输出一条开发警告提示开发者要么使用setShowId设置 id要么显式传入idprop否则useShow无法从当前 URL 推断出 id见 index.ts#L56-L59 及警告文案函数 idWarningMessage。此外queryOptions.enabled默认被设置为showId ! undefinedindex.ts#L64-L67也就是说在没有可用的 id 时查询会被自动禁用避免发起无意义的请求。Props 详解useShow的 Props 类型定义在 packages/core/src/hooks/show/types.ts由UseShowProps组合了UseOneProps同源的各类能力。下面逐一说明。resourceresource用于指定要获取数据的资源名默认从当前 URL 读取。useShow({ resource: categories, });这里有一个容易踩坑的细节如果传入了resource则当前 URL 中的id会被忽略因为该 id 可能属于另一个不同的资源。如果你仍想从当前 URL 拿到 id可以配合useParsed使用import { useShow, useParsed } from refinedev/core; const { id } useParsed(); useShow({ resource: custom-resource, id, });或者直接使用setShowId函数来设置 idimport { useShow } from refinedev/core; const { setShowId } useShow({ resource: custom-resource, }); setShowId(123);setShowId(123)会更新内部状态并触发一次新的数据请求。identifier 与同名资源如果存在多个同名的资源可以传入identifier而非资源的name。identifier仅作为资源匹配的主键dataProvider 的方法调用仍然使用在Refine/组件中定义的资源name。相关说明见Refine/组件的identifier文档。idid会被作为参数传递给 dataProvider 的getOne方法用于决定要获取哪条记录。默认从当前 URL 读取。useShow({ id: 123, });metameta是一个特殊属性用于向 dataProvider 方法传递额外信息主要有两大用途针对特定场景定制 dataProvider 方法的行为使用纯 JavaScript 对象JSON生成 GraphQL 查询。下面的示例把headers属性放进meta对象并传递给getOne方法。基于同样的思路你可以向 dataProvider 方法传递任意属性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, }; }, //... };在源码层面meta的合并逻辑值得注意。useShow先通过useMeta()获取上下文 meta再与本 Hook 传入的meta合并index.ts#L49-L54const getMeta useMeta(); const combinedMeta getMeta({ resource, meta: meta, });随后combinedMeta会传给useOne由useOne在调用getOne时把 meta连同prepareQueryContext注入的查询上下文一并下发useOne.ts#L184-L192。测试用例也验证了 meta 的聚合行为在 index.spec.tsx#L166-L201 中同时从资源定义meta: { dip: dop }、Hook 参数meta: { foo: bar }和路由参数params: { baz: qux }三层来源传入 meta最终断言getOne收到的 meta 同时包含foo、baz、dip三个键。更多关于meta概念的说明可参考 General Concepts 文档。dataProviderName当应用中配置了多个 dataProvider 时可以通过dataProviderName指定使用哪一个。当你为不同资源使用不同 dataProvider 时非常有用useShow({ dataProviderName: second-data-provider, });在 useOne.ts#L135-L141 中pickDataProvider会根据identifier、dataProviderName与资源列表选择正确的 provider并通过useDataProvider()获取其getOne方法。queryOptionsqueryOptions用于向底层useQuery传递附加选项例如控制重试次数、是否启用查询等useShow({ queryOptions: { retry: 3, enabled: false, }, });从 useOne.ts#L170-L199 可以看到这些选项最终会展开到useQuery上且enabled的默认判定逻辑是如果显式传入了queryOptions.enabled则以传入值为准否则要求resource与id均已定义才启用查询。queryOptions的具体选项说明可参考 TanStack Query v5 的useQuery文档。successNotification该属性依赖NotificationProvider才能生效。当数据获取成功后useShow会调用NotificationProvider的open函数展示成功通知。通过该属性可以自定义通知内容useShow({ successNotification: (data, values, resource) { return { message: ${data.title} Successfully fetched., description: Success with no errors, type: success, }; }, });源码中成功通知的处理在 useOne.ts#L202-L218当queryResponse.isSuccess且存在数据时若successNotification是函数则以(data, values, resource)为参数调用它得到配置再交给handleNotification展示。errorNotification该属性依赖NotificationProvider才能生效。当数据获取失败时useShow会调用NotificationProvider的open函数展示错误通知。通过该属性可以自定义错误通知useShow({ errorNotification: (data, values, resource) { return { message: Something went wrong when getting ${data.id}, description: Error, type: error, }; }, });在 useOne.ts#L221-L248 中错误分支除了处理自定义errorNotification外还会调用checkErroruseOnError触发全局错误处理并使用默认文案Error (status code: ...)展示兜底通知。liveMode该属性依赖LiveProvider才能生效。决定当收到相关的实时事件live event时是否自动更新数据auto 表示自动更新manual 表示手动更新。可用于在整个应用中实时更新和展示数据useShow({ liveMode: auto, });更多 liveMode 的说明可参考 Live / Realtime 页面。onLiveEvent该属性依赖LiveProvider才能生效。当订阅的新事件到达时执行的回调函数useShow({ onLiveEvent: (event) { console.log(event); }, });liveParams该属性依赖LiveProvider才能生效。用于传递给 liveProvider 的subscribe方法的参数。在 useOne.ts#L150-L168 中useResourceSubscription会以resources/${resource?.name}作为 channel、[*]作为订阅类型发起订阅并把liveParams展开进订阅参数同时把liveMode与onLiveEvent一并传入。overtimeOptions当请求耗时过长时你可能想展示一个「加载中」提示这时可以传入overtimeOptionsinterval时间间隔单位毫秒onInterval每个间隔触发时调用的函数。Hook 会返回一个overtime对象其中的elapsedTime表示已经过去的毫秒数当请求完成时elapsedTime会变为undefined。const { overtime } useShow({ //... overtimeOptions: { interval: 1000, onInterval(elapsedInterval) { console.log(elapsedInterval); }, }, }); console.log(overtime.elapsedTime); // undefined, 1000, 2000, 3000 4000, ... // 你可以这样使用 { elapsedTime 4000 divthis takes a bit longer than expected/div; }在源码实现中useShow把overtimeOptions原样传给useOne由useOne内部的useLoadingOvertime基于queryResponse.isFetching状态驱动计时useOne.ts#L250-L253。对应的测试 index.spec.tsx#L301-L340 验证了当getOne人为延迟 1000ms、interval设为 100ms 时请求期间overtime.elapsedTime会累加测试断言为 900msonInterval被调用请求完成后elapsedTime变为undefined。实时更新Realtime Updates该功能需要配置LiveProvider才能生效。当useShow挂载时它会调用liveProvider的subscribe方法并传入channel、resource等参数。这在需要订阅实时更新的场景中非常有用——例如某条记录的字段被其他用户修改后详情页可以自动刷新展示最新数据。如上一节所述这一订阅行为由useOne内部的useResourceSubscription完成订阅的 channel 为resources/${resource?.name}且会根据liveModeauto / manual决定收到事件后是否自动更新。返回值Return Valuesqueryquery是 TanStack QueryuseQuery的返回对象包含isFetching、isLoading、isError、refetch、data等全部查询控制项。具体字段可参考 TanStack Query v5 的useQuery文档。result除了queryuseShow还额外返回解构好的result即query.data?.data也就是getOne返回的data字段本体见 useOne.ts#L257让组件可以直接使用无需手动解构。showIdshowId是useShow当前使用的 id 值。setShowId当你希望根据用户操作改变showId时可以使用这个 setterconst { setShowId } useShow(); // 在某次用户操作中切换要展示的记录 setShowId(456);setShowId改变showId后会触发一次新的请求来获取对应 id 的数据。从源码看它就是useResourceParams返回的setIdindex.ts#L43-L47。测试 index.spec.tsx#L137-L164 验证了这一行为初始从路由拿到showId 1调用setShowId(3)后showId变为3同样通过rerender改变传入的idprop 后showId也会同步更新。overtimeovertime对象由 Hook 返回elapsedTime为已过去的毫秒数请求完成后变为undefinedconst { overtime } useShow(); console.log(overtime.elapsedTime); // undefined, 1000, 2000, 3000 4000, ...API 参考Props 汇总属性说明默认值resource资源名用于 API 数据交互从 URL 的:resource读取id数据项 ID用于 API 数据交互从 URL 的:id读取meta传递给 dataProvidergetOne的附加元数据—dataProviderName目标 dataProvider 名称defaultqueryOptionsTanStack QueryuseQuery的选项—successNotification自定义成功通知内置默认通知errorNotification自定义错误通知内置默认错误通知liveMode实时更新模式auto / manual / offoffonLiveEvent订阅事件到达时的回调—liveParams传递给 liveProvidersubscribe的参数—overtimeOptions超时加载选项interval、onInterval—Props 的完整类型定义见 types.ts。类型参数Type Parameters属性说明类型默认值TQueryFnData查询函数返回的数据继承自BaseRecordBaseRecordBaseRecordTError自定义错误对象继承自HttpErrorHttpErrorHttpErrorTDataselect函数返回的数据继承自BaseRecord未指定时默认使用TQueryFnDataBaseRecordTQueryFnData返回值类型属性说明类型query单条记录查询的结果QueryObserverResult{ data: TData; error: TError }result查询到的记录数据本体TData \| undefinedshowId记录 idBaseKey \| undefinedsetShowIdshowId的 setterDispatchSetStateActionBaseKey \| undefinedovertime超时加载属性{ elapsedTime?: number }实践建议与总结综合官方文档与源码实现使用useShow时有几个值得遵循的要点详情页零配置起步只要路由遵循 Refine 的资源路由约定如/posts/show/:iduseShow()即可自动工作无需手动传参跨资源展示记得显式传参一旦传入resourceURL 中的 id 会被忽略请通过useParsedid或setShowId显式指定要展示的记录善用setShowId实现记录切换列表、上一条/下一条等交互场景下调用setShowId即可自动触发新请求无需自己管理状态用meta打通自定义 dataProvider无论是加请求头还是生成 GraphQL 查询meta都是向getOne传递上下文的标准通道配合queryOptions.enabled控制请求时机id 尚未就绪时查询默认不会执行可结合enabled精细控制实时与超时体验配置LiveProvider后可通过liveMode实现自动刷新用overtimeOptions在慢请求时给出友好的加载反馈。useShow的核心价值在于把「路由解析 → 参数推导 → 数据获取 → 缓存与实时更新 → 通知与超时处理」这条链路完整封装起来让开发者可以用最少的样板代码构建出健壮、可实时响应、体验友好的详情展示页面。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考