拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Metabase Embedded Analytics SDK 的 useAction Hook 完整指南:触发预置 Action、类型化结果与错误处理

Metabase Embedded Analytics SDK 的 useAction Hook 完整指南触发预置 Action、类型化结果与错误处理【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabaseuseAction是 Metabase 嵌入式分析 SDKEmbedded Analytics SDK中用于触发 Metabase 中已预置pre-existingAction的 React Hook。它把执行 Action、拿到结构化结果、捕获执行错误这一整套流程封装进一个 hook 状态机让宿主应用可以在自己的按钮、表单和事件处理器中安全地调用 Metabase 的写操作Create / Update / Delete / Bulk / SQL。阅读本文后你将掌握useAction的完整签名、五个ActionKind与判别联合结果类型、ActionExecuteError错误模型以及从事件处理器手动触发 execute的正确使用范式。一、useAction 是什么在 Metabase 中Action 是运行在模型Model之上的可写操作包括隐式basic / implicit动作 Create、Update、Delete以及自定义 SQL 动作与批量bulk动作。useAction让嵌入式宿主应用即使用 SDK 的外部 React 应用直接触发这些已存在的 Actionfunction useActionTParameters, TKind( actionId: SdkActionId | null, ): UseActionResultTParameters, TKind;第一个参数actionId是 Action 的数字 id或者是它的entity_id字符串泛型TParameters用于类型化execute的参数对象可选泛型TKind用于类型化判别联合discriminated union形态的result。SDK 文档对其语义的官方描述是Triggers a pre-existing Metabase action——即该 hook只负责触发不负责创建 Action。Action 本身需要在 Metabase 后台模型详情的 Actions 选项卡中预先配置好包括每个参数的类型、必填与否与默认值。二、函数签名与类型参数完整签名如下默认类型参数在 TypeScript 中可省略function useAction TParameters extends Recordstring, unknown Recordstring, unknown, TKind extends ActionKind | undefined undefined, ( actionId: SdkActionId | null, ): UseActionResultTParameters, TKind;类型参数Type Parameter约束说明TParametersRecordstring, unknown描述execute调用时传入的参数对象例如{ name: string; email: string }TKindActionKind|undefined声明该 Action 的种类用于把result收窄为对应的判别联合结果形状省略时回退到AnyActionResult联合TKind的可选值为五种字符串字面量定义在ActionKindtype ActionKind create | update | delete | bulk | sql;它是一层扁平的公开种类联合create/update/delete恒指单行操作bulk覆盖任意批量变体sql指自定义 SQL Action。SDK 文档明确指出这五种值映射到后端命名空间的row/*与bulk/*implicitKind以及query的type值——create/update/delete对应后端的row/create、row/update、row/delete隐式种类sql对应后端的query类型 Action。参数ParameterType说明actionIdSdkActionId|null目标 Action 的标识符传null表示暂不绑定任何 ActionSdkActionId定义如下type SdkActionId number | SdkEntityId;即它既可以是 Action 的数字主键 id也可以是 Metabase 全局唯一的entity_id字符串。数字 id 适合在已知 Action 时直接硬编码或从接口读取entity_id字符串则适合跨环境开发 / 生产 / 多实例稳定引用同一个 Action。三、返回值UseActionResultuseAction返回UseActionResult对象它是一个完整的执行状态机包含五个成员PropertyType说明errorActionExecuteError|null最后一次抛出的错误已归一化为公开的ActionExecuteError形状没有错误时为nullexecute(parameters:TParameters) PromiseActionResultForKindTKind \| null用给定参数触发 Action。成功时返回响应体失败时同时抛错并写入error供渲染期消费者读取isExecutingboolean当前是否正在执行中可用于按钮 loading 态reset() void清空result与errorresultActionResultForKindTKind |null最后一次的响应首次调用前以及调用reset()之后为nullexecute 的两个关键行为成功与失败双通道execute成功时 resolve 出响应体失败时throw并且同一个错误会同步存入error状态。这意味着你可以选择两种消费方式——在事件处理器里try/catch做流程控制或在渲染层读取error?.data?.message展示错误信息二者拿到的都是同一个归一化错误对象。空值短路当actionId为null或 SDK 尚未初始化完成时execute不会发起任何网络请求而是直接 resolve 为null。SDK 文档建议如果宿主应用中这些情况可达调用方应在事件处理器里先用if (!actionId) return;自行防护避免点了按钮却没反应的困惑。四、不传 TKindAnyActionResult 与类型收窄如果不提供第二个泛型TKind即保持默认undefinedresult的类型会是AnyActionResult——所有可能响应体的联合type AnyActionResult | ActionResultForCreate | ActionResultForUpdate | ActionResultForDelete | ActionResultForBulk | ActionResultForSql;SDK 文档特别强调当作者在编写时并不知道 Action 的种类使用默认联合类型依然能得到TS 可收窄的形状——通过key in result进行类型守卫type guard而不是从宽松的Recordstring, unknown强转。后者会吞掉错误的字段读取mispelled reads 在编译期无法暴露前者则能让 TypeScript 在in判断之后自动推导出具体的结果形状。const { result } useAction{ id: number }(actionId); // result 是 AnyActionResult | null if (result created-row in result) { // 此处 TS 自动收窄为 ActionResultForCreate const inserted result[created-row]; } else if (result rows-affected in result) { // 此处 TS 自动收窄为 ActionResultForSql console.log(result[rows-affected]); }五、五种判别联合结果形状TKind通过ActionResultForKind这个条件类型把result收窄到唯一确定的结果形状type ActionResultForKindTKind TKind extends create ? ActionResultForCreate : TKind extends update ? ActionResultForUpdate : TKind extends delete ? ActionResultForDelete : TKind extends bulk ? ActionResultForBulk : TKind extends sql ? ActionResultForSql : AnyActionResult;各结果形状分别定义如下均来自 SDK API 文档create —— 单行插入ActionResultForCreate返回被插入的那一行type ActionResultForCreate { created-row: Recordstring, RowValue; };update —— 单行更新ActionResultForUpdate返回受影响行的主键type ActionResultForUpdate { rows-updated: readonly RowValue[]; };delete —— 单行删除ActionResultForDelete返回受影响行的主键type ActionResultForDelete { rows-deleted: readonly RowValue[]; };bulk —— 批量变体ActionResultForBulk返回一个成功标志加可选的行数统计type ActionResultForBulk { rows-created?: number; rows-deleted?: number; rows-updated?: number; success: boolean; };sql —— 自定义 SQL ActionActionResultForSql返回受影响行数type ActionResultForSql { rows-affected: number; };其中RowValue是 Metabase 查询结果与 Action 响应中单个值的类型type RowValue string | number | null | boolean | object;六、错误模型ActionExecuteErrorexecute失败时非 2xx 响应抛出的错误会被归一化并捕获进 hook 的error状态其形状定义在ActionExecuteErrortype ActionExecuteError { data: { errors?: Recordstring, string; message?: string; }; isCancelled: boolean; status?: number; };PropertyType说明data.message?string对终端用户可操作的诊断信息actionable diagnosticdata.errors?Recordstring, string后端报告参数级校验失败时的逐字段映射{ slug: message }isCancelledboolean是否被取消status?numberHTTP 状态码传输层失败离线、请求被中止未收到 HTTP 响应时该字段不存在hook 把error的类型声明为ActionExecuteError | null因此消费者可以直接读取字段无需任何类型断言const message error?.data?.message;关于errors与message的关系SDK 文档给出了关键区分参数级校验失败时error.data.errors是逐字段的映射整体请求失败例如外键约束违反时则是{ message: ..., errors: {} }这样的形态——即只有全局message而没有逐字段错误。这在表单场景中非常实用你可以把errors渲染到对应字段下方把message渲染为表单顶部的整体错误提示。七、与查询 hooks 的本质区别手动触发 executeuseAction与 SDK 中的查询类 hooks如useMetabot、查询结果类 hooks有一个关键差异Unlike the query hooks, this does NOT run on mount——useAction不会在组件挂载时自动执行。它完全由调用方从事件处理器如按钮onClick、表单onSubmit中显式调用execute来触发。这样设计是合理的Action 是写操作绝不能在挂载时无意识地执行否则每次打开页面都会插入 / 更新 / 删除数据。由此也引出一个重要的使用范式——条件执行的判断放在事件处理器中而不是依赖 hook 内部的状态function handleClick() { if (!user.canEdit) return; // 权限门控 if (!actionId) return; // Action 未就绪 execute({ name, email }); }SDK 文档给出的示例即是如此if (!user.canEdit) return;之后再调用execute。八、完整实战示例类型化创建用户综合以上全部知识一个完整的表单提交触发 create 类型 Action的宿主端组件可以这样写import { useAction } from metabase/embedding-sdk-react; type CreateUserParams { name: string; email: string }; function CreateUserForm({ actionId }: { actionId: number | null }) { const { execute, isExecuting, error, result, reset } useAction CreateUserParams, create (actionId); const handleSubmit async (params: CreateUserParams) { if (!actionId) return; // actionId 为空则不发起请求 if (!params.email.includes()) return; try { const res await execute(params); // 因为 TKind createres 被收窄为 // ActionResultForCreate | null if (res) { console.log(inserted row:, res[created-row]); } } catch (e) { // 失败时 execute 抛错同一错误也已在 error 状态中 console.error(e); } }; return ( form onSubmit{(e) { e.preventDefault(); handleSubmit({ name, email }); }} {/* 字段编辑区 */} button typesubmit disabled{isExecuting || !actionId} {isExecuting ? Saving… : Create} /button {/* 渲染期读取归一化错误 */} {error p rolealert{error.data?.message}/p} {result pCreated row: {JSON.stringify(result[created-row])}/p} button typebutton onClick{reset}Reset/button /form ); }要点回顾TParameters用CreateUserParams声明execute(params)的参数因此获得完整类型检查TKind create让result与execute的 resolve 值被收窄为ActionResultForCreate可直接读取created-rowisExecuting驱动按钮 loading 态避免重复提交渲染层直接读error.data?.message无需类型断言reset()用于表单重新打开或提交成功后清空上次的result与error。九、后端执行链路印证SDK 侧的类型与语义设计与后端 Action 执行实现是严格对应的。在 src/metabase/actions/execution.clj 中execute-custom-action!按action-type分发:query类型走execute-query-action!执行写查询:http类型走http-action/execute-http-action!。这印证了ActionKind中sql后端query类型与其它种类的划分依据。execute-query-action!会把请求参数按参数 id 装配进查询的:parameters再通过qp/execute-write-query!在写连接上执行——这正是execute(parameters)中参数对象被发送到后端并被逐个匹配到 Action 参数槽的底层链路。隐式 Action 的种类映射定义在 legacy-current:row/create、:row/update、:row/delete对应到:model.row/create、:model.row/update、:model.row/delete——这正是ActionKind文档中create/update/delete对应后端命名空间row/*implicitKind这一说法的代码出处。后端还实现了check-no-extra-parameterssrc/metabase/actions/execution.clj#L98-L111当请求参数中存在没有对应目标参数槽的键时返回 400 并携带:type :invalid-parameter与:parameters——对应前端ActionExecuteError.data中参数相关错误的来源。此外关于隐式basic动作本身的创建与限制只能基于包装单一原始表的模型、只支持 Create/Update/Delete 三种、不可归档只能开关可进一步参阅 docs/actions/basic.md 与 docs/actions/introduction.md自定义 SQL Action 的编写方式见 docs/actions/custom.md。十、相关 API 速查API类型说明useActionHook触发已存在的 Metabase ActionUseActionResult接口hook 返回值error/execute/isExecuting/reset/resultSdkActionId类型别名number \| SdkEntityIdAction 的数字 id 或entity_idActionKind类型别名create \| update \| delete \| bulk \| sqlActionResultForKind类型别名按TKind条件映射到具体结果形状AnyActionResult类型别名所有结果形状的联合TKind缺省时的result类型ActionExecuteError类型别名归一化执行错误data.message、data.errors、status、isCancelledActionResultForCreate类型别名{ created-row }插入的行ActionResultForUpdate类型别名{ rows-updated }受影响主键ActionResultForDelete类型别名{ rows-deleted }受影响主键ActionResultForBulk类型别名{ success, rows-created?/deleted?/updated? }ActionResultForSql类型别名{ rows-affected }受影响行数RowValue类型别名string \| number \| null \| boolean \| object总结useAction是嵌入式宿主应用与 Metabase 写能力之间的桥梁。用好它只需记住三条核心纪律一是始终从事件处理器手动调用execute绝不在挂载期自动执行写操作二是尽量在调用时声明TKind以获得判别联合的完整类型收窄无法预先确定时则用key in result做类型守卫三是错误处理走error.data.message全局与error.data.errors逐字段双通道配合isExecuting与reset()完成完整的执行状态管理。【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门