
Refine v5 Chakra UI DeleteButton 组件全解从二次确认弹层到 dataProvider 删除调用链【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine本文以 Refine 仓库中的 Chakra UI 集成文档为骨架系统讲解DeleteButton组件的完整用法与底层原理。你将掌握如何在列表、编辑、详情页中安全地触发删除操作理解recordItemId、resource、accessControl等核心属性的取值规则并沿源码看清从按钮点击、确认弹层到dataProvider.deleteOne的完整调用链可直接落地到管理后台与内部工具的删除场景中。组件概览基于 Chakra UI Button 与 Popover 的删除确认流程DeleteButton是 Refine 提供给 Chakra UI 用户的删除动作按钮其设计目标非常明确删除是不可逆的高危操作必须经过用户二次确认。因此在实现上它组合了 Chakra UI 的两个基础组件Button—— 触发删除的入口按钮默认使用colorSchemered与variantoutline的红色描边样式配以 Trash 图标从视觉上提示这是破坏性操作Popover—— 点击按钮后弹出的确认层包含确认标题、确认按钮与取消按钮用户确认后才真正执行删除。当用户点击确认后组件会调用由dataProvider提供的useDelete方法向数据源发起删除请求。这一点在源码注释中有明确说明When confirmed it executes theuseDeletemethod provided by yourdataProvider见 delete/index.tsx 顶部 JSDoc。另一个值得关注的特性是swizzle定制化文档明确提示你可以使用Refine CLI将本组件弹出到项目源码中自由改造。Refine CLI 的 swizzle 命令会复制组件源码到本地使你可以脱离包内实现按业务需求重写样式与交互再替换默认组件。快速上手在列表页中集成 DeleteButton文档给出的最典型应用场景是列表页的操作列每一行数据提供一个删除按钮点击后确认删除对应记录。完整示例如下结合refinedev/react-table与 TanStack Table 渲染表格import { List, DeleteButton, } from refinedev/chakra-ui; import { TableContainer, Table, Thead, Tr, Th, Tbody, Td, } from chakra-ui/react; import { useTable } from refinedev/react-table; import { ColumnDef, flexRender } from tanstack/react-table; const PostList: React.FC () { const columns React.useMemoColumnDefIPost[]( () [ { id: id, header: ID, accessorKey: id, }, { id: title, header: Title, accessorKey: title, }, { id: actions, header: Actions, accessorKey: id, cell: function render({ getValue }) { return ( DeleteButton recordItemId{getValue() as number} / ); }, }, ], [], ); const { reactTable: { getHeaderGroups, getRowModel }, } useTable({ columns, }); return ( List TableContainer Table variantsimple whiteSpacepre-line Thead {getHeaderGroups().map((headerGroup) ( Tr key{headerGroup.id} {headerGroup.headers.map((header) { return ( Th key{header.id} {!header.isPlaceholder flexRender( header.column.columnDef.header, header.getContext(), )} /Th ); })} /Tr ))} /Thead Tbody {getRowModel().rows.map((row) { return ( Tr key{row.id} {row.getVisibleCells().map((cell) { return ( Td key{cell.id} {flexRender( cell.column.columnDef.cell, cell.getContext(), )} /Td ); })} /Tr ); })} /Tbody /Table /TableContainer /List ); }; interface IPost { id: number; title: string; }这段代码的核心在于cell渲染函数通过getValue()取出当前行的id并以recordItemId传入DeleteButton从而让按钮精确锁定删哪一行。运行时需要在Refine中注册posts资源含list: /posts路由再配合 React Router 挂载即可。核心属性精讲文档将组件属性归纳为recordItemId、resource、onSuccess、hideText、accessControl五类下面逐一展开并补充从源码确认的默认值与边界行为。recordItemId指定要删除哪条记录recordItemId用于显式指定将被删除的记录 ID。默认情况下该值会从路由参数中推断——例如在/posts/edit/1这样的路由下Refine 会解析出id 1。当按钮不在带 id 的路由上、或列表页需要按行注入 id 时必须显式传入import { DeleteButton } from refinedev/chakra-ui; const MyDeleteComponent () { return ( DeleteButton resourceposts recordItemId123 / ); };点击该按钮后会触发useDelete方法删除resource posts、id 123的记录。类型定义中recordItemId的类型为BaseKey见 ui-types 的 RefineButtonSingleProps即string | number均可。通用测试中还验证了传入recordItemIdrecord-id时deleteOne会收到{ id: record-id }的调用参数见 ui-tests 的 delete 测试。resource指定删除哪个资源的记录resource用于指定删除操作所属的资源。默认情况下同样从路由参数推断。当按钮需要操作非当前路由的资源时显式传入import { DeleteButton } from refinedev/chakra-ui; const MyDeleteComponent () { return DeleteButton resourcecategories recordItemId123 /; };此时点击按钮将删除categories资源下 id 为123的记录。文档还特别说明了一个细节如果存在多个同名资源可以传identifier代替name。identifier只作为资源的主匹配键使用而 data provider 方法仍然使用Refine/组件中定义的资源name来调用。这保证了在复杂多资源场景下按钮既能精确定位 UI 资源又不影响 API 调用语义。identifier的完整语义可参考Refine/组件文档中的相关说明。onSuccess删除成功后的回调onSuccess允许你在删除请求成功返回后执行自定义逻辑比如日志输出、跳转、刷新统计等。回调参数是DeleteOneResponse类型即删除接口返回的数据import { DeleteButton } from refinedev/chakra-ui; const MyDeleteComponent () { return ( DeleteButton resourceposts recordItemId1 onSuccess{(value) { console.log(value); }} / ); };在实现层面onSuccess会被透传给useDelete的 mutation 配置项见 core 的 delete-button hook因此它只在删除真正成功后触发若请求失败则不会调用。hideText只保留图标hideText用于控制按钮是否显示文字。设为true时按钮只显示垃圾桶图标Trash Icon适合在表格行内等紧凑空间使用import { DeleteButton } from refinedev/chakra-ui; const MyDeleteComponent () { return ( DeleteButton hideText{true} / ); };从源码看hideText的默认值是false为true时组件渲染 Chakra UI 的IconButton带aria-label{title}保证可访问性否则渲染带leftIcon与文字的普通Button见 delete/index.tsx 与#L81-L110。accessControl接入权限控制accessControl用于将按钮与 Refine 的权限系统accessControlProvider联动。该属性仅在Refine/提供了accessControlProvider时生效包含两个子选项enabled是否启用访问控制检查默认值为truehideIfUnauthorized用户无权限时是否直接隐藏按钮而非仅禁用。import { DeleteButton } from refinedev/chakra-ui; export const MyListComponent () { return ( DeleteButton accessControl{{ enabled: true, hideIfUnauthorized: true, }} / ); };需要说明的是enabled的默认值还受全局配置影响accessControlProvider.options.buttons中的enableAccessControl与hideIfUnauthorized提供了全局开关组件属性可以在单按钮层面覆盖全局配置。通用测试覆盖了全局配置与组件属性四种组合的完整矩阵全局开/关 × 属性开/关并验证了无权限时的两种表现默认禁用并显示拒绝原因文本reason会作为按钮的title属性启用hideIfUnauthorized时完全不渲染见 ui-tests 的 access control 测试块。源码剖析从点击确认到 dataProvider.deleteOne 的完整调用链理解组件行为最好的方式是阅读实现。Chakra UI 的DeleteButton本身很薄——它从refinedev/core引入useDeleteButtonhook 获取全部业务逻辑然后专注渲染见 delete/index.tsx。调用链如下DeleteButton 点击 → Popover 确认 → useDeleteButton().onConfirm() → useResourceParams() 解析 id / resource / identifier → useDelete().mutate({ id, resource: identifier, mutationMode, ... }) → dataProvider.deleteOne() → 成功回调 onSuccessuseDeleteButton的核心逻辑位于 packages/core/src/hooks/button/delete-button/index.tsx关键环节包括资源与 ID 解析通过useResourceParams根据传入的resource/id与当前路由推导出实际使用的id、resource和identifier。权限检查通过useButtonCanAccess执行action: delete的权限校验产出disabled、hidden与canAccess状态与上述accessControl属性直接对应。文案国际化按钮文案全部走 i18n 翻译键——buttons.delete默认 Delete同时作为确认按钮文字、buttons.confirm默认 Are you sure?、buttons.cancel默认 Cancel。hook 的测试专门验证了默认文案与自定义 i18nProvider 两种情形见 core 的 hook 测试。loading 状态loading id variables?.id isPending——只有当前按钮对应记录正在请求时才显示加载态。hook 测试专门验证了 id1 与 id2 两个按钮互不干扰见 同文件这对表格多行场景非常重要。确认执行onConfirm中先调用setWarnWhen(false)清除未保存更改警告再以identifier作为资源名调用useDelete().mutate并透传mutationMode、successNotification、errorNotification、meta、dataProviderName、invalidates。UI 层Chakra UI 实现则负责确认交互的呈现点击按钮用useState控制Popover开合确认区渲染取消 删除两个按钮确认按钮colorSchemered且autoFocus见 delete/index.tsx无论哪种形态按钮都带有data-testid{RefineButtonTestIds.DeleteButton}与className{RefineButtonClassNames.DeleteButton}便于自动化测试与全局样式定位。测试如何保障删除行为正确性仓库通过两层测试共同保障DeleteButton的行为跨 UI 框架的通用测试packages/ui-tests导出buttonDeleteTests由各 UI 包分别绑定自己的组件执行Chakra UI 侧见 delete/index.spec.tsx通用测试实现见 ui-tests/delete.tsx。它验证了默认渲染、disabled禁用、hidden隐藏、正确的 test-id、children覆盖文字、hideText只显图标、点击后弹出 Are you sure? / Cancel / Delete 确认层、确认后deleteOne被调用、onSuccess触发、自定义confirmTitle/confirmOkText/confirmCancelText生效、自定义mutationMode与resource渲染等。core hook 层测试直接对useDeleteButton验证文案、i18n、loading 状态隔离与meta向accessControlProvider的透传见 index.spec.tsx。这两层测试共同确保了无论使用 Chakra UI、MUI 还是 Mantine删除按钮的确认后删除语义是一致的。完整属性参考DeleteButton的类型由RefineDeleteButtonProps定义见 ui-types/button.tsx除文档详解的属性外还包含以下常用配置属性说明默认值recordItemId要删除的记录 ID类型BaseKey从路由:id推断resource目标资源名可用identifier替代从路由推断accessControl{ enabled?, hideIfUnauthorized? }权限控制{ enabled: true }可被全局配置覆盖onSuccess删除成功后的回调参数为DeleteOneResponse—hideText仅显示图标falsemutationMode删除的 mutation 模式pessimistic/optimistic/undoable继承Refine/的mutationMode设置successNotification/errorNotification自定义成功/失败通知资源默认通知meta透传给 data provider 的附加数据—dataProviderName指定调用的 data providerdefaultinvalidates删除成功后要失效的查询键[list, many]confirmTitle确认弹层标题i18nbuttons.confirm→ Are you sure?confirmOkText确认按钮文字i18nbuttons.delete→ DeleteconfirmCancelText取消按钮文字i18nbuttons.cancel→ CancelsvgIconProps自定义 Trash 图标属性—children覆盖按钮文字i18nbuttons.deletedisabled/hidden禁用 / 隐藏按钮false此外组件还接受 Chakra UIButton的全部原生 propsonClick、size、variant等因此可以无缝融入既有 Chakra UI 主题体系。小结DeleteButton是 Refine Chakra UI 栈中处理删除动作的标准答案开箱即用的红色危险样式、内建的 Popover 二次确认、从路由自动推断的recordItemId/resource、可选的数据权限控制与 i18n 文案加上 swizzle 定制能力让删除这一高危操作既安全又灵活。结合 源码实现 与 core 层 hook 阅读可以清晰把握UI 渲染与数据逻辑的边界——前者交给各 UI 框架适配层后者统一收敛在refinedev/core这正是 Refine 跨 UI 框架保持一致行为的关键设计。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考