refine useResourceWithRoute 钩子:按路由名获取资源定义,及其在 v4 中的现代替代方案 useResource
2026/9/14 13:58:46 网站建设 项目流程

refine useResourceWithRoute 钩子:按路由名获取资源定义,及其在 v4 中的现代替代方案 useResource

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

本篇以 refine(v3 版本 API 参考)中的useResourceWithRoute钩子为核心,讲清它的设计定位——从<Refine>组件的resources数组中按路由名反查资源对象、其返回值类型与典型用法,并结合当前仓库源码说明该钩子为何被标记为 deprecated,以及在新路由体系下应如何使用useResourceuseResourceParams完成同样的资源解析。读完后,你将能在旧项目中正确使用该钩子,并掌握在新项目中获取资源定义、路由参数与 action 的推荐方式。

useResourceWithRoute 是什么

useResourceWithRoute用于按路由名(route name)获取resources数组中定义的资源对象。这些resources是开发者在<Refine>组件上声明的资源列表,每个资源项包含nameroutelist/create/edit/show等路由与页面配置。

根据 v3 API 参考文档 的明确说明,这个钩子有两个关键定位:

  • 它是 refine内部使用的钩子(used internal in refine),正常情况下业务代码不需要直接调用;
  • 官方仍将其导出,是因为部分使用场景下它会很有用(we export it as it may be useful for some use-cases)。

也就是说,它是一个"半内部"工具:你在自定义路由组件、自绘菜单或需要"当前 URL 对应哪个资源"这类逻辑时,可以借助它拿到资源定义;但日常 CRUD 开发中,绝大多数场景不需要触碰它。

用法示例

文档给出的标准用法如下(摘自 useResourceWithRoute.md):

import { useResourceWithRoute } from "@pankod/refine-core"; const resourceWithRoute = useResourceWithRoute(); const resource = resourceWithRoute("posts");

要点解析:

  1. useResourceWithRoute()本身不接收参数,调用后返回一个函数resourceWithRoute
  2. 向该函数传入路由名(如"posts"),它会到<Refine>声明的resources数组中匹配出对应的资源对象并返回;
  3. 返回的资源对象类型是IResourceItem,即你在resources数组中定义的那个资源项(含nameroutelabel、各 action 组件配置等)。

API Reference 与返回值

原始文档的 API 部分很简洁,其返回值定义如下:

描述类型
resourceWithRoute(route: string) => IResourceItem

即钩子返回一个函数,入参为字符串类型的路由名,出参为IResourceItem资源对象。

要理解这个返回值的实际内容,需要看IResourceItem的构成。v3 文档中 useResource 参考页 给出了该接口的完整形态:

interface IResourceItem extends IResourceComponents { name: string; // 资源名,也是传给 dataProvider 的 resource 参数 label?: string; // 用于菜单、面包屑等展示 route?: string; // 路由名,useResourceWithRoute 就是按它匹配的 icon?: ReactNode; canCreate?: boolean; canEdit?: boolean; canShow?: boolean; canDelete?: boolean; options?: OptionsProps; parentName?: string; // 嵌套资源时指向父资源 }

其中IResourceComponents声明了listcreateeditshow四个可选页面组件。文档还特别指出:canCreatecanShowcanEdit等布尔属性会在对应组件定义于resources自动生成,即你配了edit组件,canEdit即为true

从接口结构可以推断,useResourceWithRoute的工作流程是:以传入的 route 字符串为 key,在resources数组中查找route(或name)相等的项,返回整个资源对象——这正是"按路由名反查资源"语义的来源。

同族钩子 useResource(v3 版本)

useResourceWithRoute同属 v3 资源类钩子的是useResource,两者关系需要分清:

  • useResource返回resources数组本身,以及从当前路由和 query 参数推断出的resourceresourceNameidaction
  • 它也支持通过resourceNameOrRouteName属性按名称取资源:
import { useResource } from "@pankod/refine-core"; const { resource } = useResource({ resourceNameOrRouteName: "posts", });
  • useResourceWithRoute只暴露"route → 资源对象"这一个函数式能力,定位更窄。

v3 文档中useResource的返回值包括:

字段含义
resources<Refine>中定义的IResourceItem[]
resource当前资源对象
resourceName资源名
idquery 参数id
actionquery 参数actioncreate|edit|show|clone|undefined

现状:已废弃,仅限旧路由体系

需要注意一个关键事实:useResourceWithRoute在当前版本(v4 及以上)中已被废弃。仓库的 packages/core/CHANGELOG.md 在描述新路由体系的迁移说明中明确写道:

useResourceWithRouteis now deprecated and only works with the legacy routing system.

即:该钩子只与旧版(legacy)路由系统兼容。如果你维护的是 v3 老项目、仍在使用 legacy 路由,可以继续沿用文档中的用法;但如果新项目或已完成 v4 迁移,应改用新的资源类钩子。

v4 替代实现:useResource 的当前源码

当前仓库中useResource的真实实现位于 packages/core/src/hooks/use-resource-params/use-resource/index.ts,它替代了useResourceWithRoute的"按名称/路由取资源"职责,能力更强:

export function useResource(args?: UseResourceParam): UseResourceReturnType { const { resources } = useContext(ResourceContext); const params = useParsed(); const select = (resourceName: string, force = true) => { const pickedResource = pickResource(resourceName, resources); if (pickedResource) { return { resource: pickedResource, identifier: pickedResource.identifier ?? pickedResource.name, }; } if (force) { // 未找到时创建临时资源项,保证调用方总能拿到对象 const resource = { name: resourceName, identifier: resourceName }; return { resource, identifier: resource.name }; } return undefined; }; // ... }

从源码(见 index.ts 第 56–113 行)可以确认几个关键行为:

  1. 参数语义useResource(identifier?)接受一个可选的资源标识(identifier 或 name)。传入时优先从resources中匹配;未传入时则回退到从当前路由解析出的资源useParsed()params.resource)。这覆盖了useResourceWithRoute的"按路由名查资源"场景。
  2. 容错创建:当传入的 name 在resources中不存在且forcetrue(默认)时,源码会现场构造一个{ name, identifier }的临时资源对象返回,而不是抛错——这对"操作一个未在resources中声明的临时资源"的场景很实用。
  3. 返回值{ resources, resource, select, identifier },其中select(resourceName, force)就是文档化过的"按名称选资源"函数,identifier则统一处理了资源未显式声明identifier时回退到name的逻辑。

资源类型定义现在位于 packages/core/src/contexts/resource/types.ts。与 v3 相比,IResourceComponents的四个 action(list/create/clone/edit/show)在 v4 中表示路由路径ResourceRoutePath),而labelhideiconparentdataProviderName等配置收敛到了meta中,并新增了identifier字段用于避免资源名冲突(见 types.ts 第 68–92 行)。

更底层的组合:useResourceParams

如果你的需求不只是"拿到资源对象",而是要同时推断idaction,v4 提供了组合钩子useResourceParams。它的文档注释(见 index.ts 第 32–53 行)完整描述了推断规则:

  • resource:显式传入优先(即使未在<Refine/>中声明),否则从路由推断;
  • id:显式传入优先,否则从路由推断;若自定义 resource 与路由推断的不同,则idundefined
  • action:显式传入优先,否则从路由推断;
  • formAction:仅能取edit/clone/create,resource 不一致时回退为create

其内部正是基于useResource()selectidentifier完成"显式参数 vs 路由推断"的仲裁(见 index.ts 第 54–103 行)。相关行为有对应测试覆盖,可参考 index.spec.tsx。

选型建议

场景推荐方案
v3 老项目、legacy 路由,需要按路由名反查资源useResourceWithRoute(按 v3 文档用法,见本文"用法示例")
v4+ 新项目,按名称/路由获取资源对象useResource()/useResource("posts"),需要按名查找时用返回的select
v4+ 需要同时推断 resource / id / action / formActionuseResourceParams({ resource?, id?, action? })

适用前提与限制useResourceWithRoute的用法仅在 v3 及 legacy 路由体系下有效,官方 CHANGELOG 已明确其 deprecated 状态;在新路由体系下,useParseduseResource等钩子接管了"路由 → 资源"的解析职责。如果你在 v4 代码中搜索useResourceWithRoute找不到导出,这是符合预期的——它的职责已被上文介绍的useResource完整承接。

参考文件

  • useResourceWithRoute 文档(v3)
  • useResource 文档(v3)
  • useResource 当前实现
  • useResourceParams 实现
  • 资源类型定义
  • 废弃声明所在 CHANGELOG

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

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

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

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

立即咨询