
Refine v5 中 Ant Design DeleteButton 的完整指南确认弹窗、useDelete 调用链与权限控制【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refineDeleteButton是 Refine 基于 Ant Design 二次封装的危险操作按钮组件专门用于删除场景。它集成了 Ant Design 的Button与Popconfirm点击后会弹出确认框确认后才通过 dataProvider 的deleteOne方法真正执行删除——这种先确认、后执行的设计能有效防止误删。本文围绕该组件的核心脉络展开先看它在表格中的典型用法再逐一拆解recordItemId、resource、onSuccess、mutationMode、hideText、accessControl等关键属性最后深入源码与测试讲清确认弹窗文案、useDeleteButton内部调用链以及 i18n 机制让你在管理后台中安全、优雅地实现删除功能。组件概览基于Button与Popconfirm的组合根据官方文档documentation/docs/ui-integrations/ant-design/components/buttons/delete-button/index.mdDeleteButton底层由 Ant Design 的Button与Popconfirm两个组件组合而成当你尝试删除某条数据时页面上会弹出确认气泡Popconfirm询问是否确认删除点击确认后组件会执行由 dataProvider 提供的useDelete方法真正发起删除请求。这一行为在源码中得到了完全印证。打开 packages/antd/src/components/buttons/delete/index.tsx可以看到组件的渲染结构return ( Popconfirm keydelete okText{confirmOkText ?? defaultConfirmOkLabel} cancelText{confirmCancelText ?? defaultCancelLabel} okTypedanger title{confirmTitle ?? defaultConfirmTitle} okButtonProps{{ disabled: loading }} onConfirm{onConfirm} disabled{isDisabled} Button danger loading{loading} icon{DeleteOutlined /} title{title} disabled{isDisabled} >import { List, useTable, DeleteButton, } from refinedev/antd; import { Table } from antd; const PostList () { const { tableProps } useTableIPost(); return ( List Table {...tableProps} rowKeyid Table.Column dataIndexid titleID / Table.Column dataIndextitle titleTitle width50% / Table.ColumnIPost titleActions dataIndexactions keyactions render{(_, record) ( DeleteButton sizesmall recordItemId{record.id} / )} width50% / /Table /List ); }; interface IPost { id: number; title: string; }关键点在于recordItemId{record.id}——它把当前行的记录 ID 绑定到删除按钮上。点击按钮后组件会自动推断资源名与记录 ID触发useDelete从而删除对应记录。文档中的 live 示例还展示了该页面挂载在/posts路由下资源名定义为posts。核心属性详解recordItemId指定要删除哪条记录recordItemId用于管理将要删除的记录。默认情况下它会从路由参数中自动推断例如在posts/edit/123页面中123会自动成为删除目标因此在编辑/详情页内放置删除按钮时通常可以省略。在列表页这类无法从路由推断 ID 的场景则需要显式传入import { DeleteButton } from refinedev/antd; const MyDeleteComponent () { return ( DeleteButton resourceposts recordItemId123 / ); };点击按钮后useDelete会删除资源为posts、ID 为123的记录。注意这里recordItemId传入的是字符串123而BaseKey类型同样支持数字等类型具体以你的主键类型为准。resource指定删除哪个资源的记录resource用于管理将要删除的是哪个资源的记录默认同样从路由参数推断。当需要删除其他资源的数据例如在 posts 页面里删除 categories 数据时显式传入资源名import { DeleteButton } from refinedev/antd; const MyDeleteComponent () { return DeleteButton resourcecategories recordItemId123 /; };点击后useDelete会删除资源为categories、ID 为123的记录。同名资源的处理identifier如果你在Refine/中定义了多个同名的资源可以传入identifier而非name来区分。identifier只作为资源的主匹配键dataProvider 的方法仍然使用Refine/组件中定义的资源name来执行。更详细的说明可参考 documentation/docs/core/refine-component/index.md 中的identifier小节。onSuccess删除成功后的回调onSuccess允许你在删除请求返回结果后做额外处理例如打日志、刷新统计、跳转等。文档示例中在删除成功后console.log返回值import { DeleteButton } from refinedev/antd; const MyDeleteComponent () { return ( DeleteButton resourceposts recordItemId1 onSuccess{(value) { console.log(value); }} / ); };文档配套的 live 示例还演示了一个自定义 dataProvider通过覆盖deleteOne方法模拟 500ms 延迟后返回{ message: You have successfully deleted the record }此时onSuccess收到的value就是这个自定义返回对象。这说明onSuccess拿到的是 dataProviderdeleteOne的返回值即DeleteOneResponse因此你可以利用它拿到服务端返回的业务信息而不只是请求成功这个状态。mutationMode删除的三种提交模式mutationMode决定删除操作的提交方式可选值为pessimistic默认先调用 dataProvider成功后再更新 UI最安全optimistic先更新 UI再后台调用 dataProvider响应更快但失败时需回滚undoable先更新 UI同时在指定时间内提供撤销入口超时后才真正调用 dataProvider。在表格中为单个按钮设置示例import { List, DeleteButton, useTable } from refinedev/antd; import { Table } from antd; const PostList () { const { tableProps } useTableIPost(); return ( List Table {...tableProps} rowKeyid Table.Column dataIndexid titleID / Table.Column dataIndextitle titleTitle / Table.ColumnIPost titleActions dataIndexactions render{(_, record) ( DeleteButton sizesmall recordItemId{record.id} mutationModeundoable / )} / /Table /List ); };对删除这类危险操作推荐优先使用默认的pessimisticundoable适合希望给用户反悔机会的场景删除后出现撤销提示。更完整的模式对比与配置说明见 documentation/docs/advanced-tutorials/mutation-mode.md。hideText只显示图标hideText用于控制是否显示按钮文字。设为true时按钮只保留图标DeleteOutlined适合操作列空间紧张的场景import { DeleteButton } from refinedev/antd; const MyDeleteComponent () { return ( DeleteButton hideText{true} recordItemId123 / ); };从源码可以看到hideText的默认值为false且当传入children时会优先渲染children作为按钮内容children ?? label。accessControl接入权限控制accessControl属性用于控制删除按钮的权限表现仅在向Refine/提供了accessControlProvider时生效。它支持两个子属性enabled是否启用访问控制检查默认组件本身会启用可显式控制hideIfUnauthorized用户无权限时是否直接隐藏按钮。import { DeleteButton } from refinedev/antd; export const MyListComponent () { return ( DeleteButton accessControl{{ enabled: true, hideIfUnauthorized: true, }} / ); };若不设置hideIfUnauthorized无权限时按钮通常表现为禁用而不是隐藏。完整的accessControlProvider定义可参考 documentation/docs/authorization/access-control-provider/index.md。API Reference 与外部属性该组件的属性完整定义见文档中的Properties表格refinedev/antd/DeleteButton。此外它接受 Ant DesignButton的全部 props如size、danger、icon、loading等这意味着你可以完全按 Ant Design 的按钮规范自由定制外观与行为。源码探秘useDeleteButton 的调用链DeleteButton本身是纯展示层真正的逻辑集中在 Refine Core 提供的useDeleteButton钩子中。它的实现位于 packages/core/src/hooks/button/delete-button/index.tsx核心流程如下export function useDeleteButton(props: DeleteButtonProps): DeleteButtonValues { const translate useTranslate(); const { mutation: { mutate, isPending, variables }, } useDelete(); const { setWarnWhen } useWarnAboutChange(); const { mutationMode } useMutationMode(props.mutationMode); const { id, resource, identifier } useResourceParams({ resource: props.resource, id: props.id, }); const { title, disabled, hidden, canAccess } useButtonCanAccess({ action: delete, accessControl: props.accessControl, meta: props.meta, id, resource, }); const label translate(buttons.delete, Delete); const confirmOkLabel translate(buttons.delete, Delete); const confirmTitle translate(buttons.confirm, Are you sure?); const cancelLabel translate(buttons.cancel, Cancel); const loading id variables?.id isPending; const onConfirm () { if (id identifier) { setWarnWhen(false); mutate( { id, resource: identifier, mutationMode, successNotification: props.successNotification, errorNotification: props.errorNotification, meta: props.meta, dataProviderName: props.dataProviderName, invalidates: props.invalidates, }, { onSuccess: props.onSuccess, }, ); } }; return { label, title, hidden, disabled, canAccess, loading, confirmOkLabel, cancelLabel, confirmTitle, onConfirm, }; }从源码可以提炼出以下关键事实参数兜底useResourceParams会解析resource与id当组件未显式传入时从当前路由上下文自动推断这正是文档所说默认从路由参数推断的底层实现。useDeleteButton同时返回resource与identifier后者用于在mutate时作为resource参数传递。确认框文案走 i18n按钮文字buttons.delete、确认标题buttons.confirm→ Are you sure?、确认/取消按钮文字buttons.delete/buttons.cancel全部通过useTranslate读取未命中时使用内置英文默认值。删除走useDelete确认后调用useDelete的mutate并携带mutationMode、successNotification、errorNotification、meta、dataProviderName、invalidates等参数onSuccess作为 mutation 回调传入。useDelete的完整说明见 documentation/docs/data/hooks/use-delete/index.md其底层通过 dataProvider 的deleteOne方法发起请求dataProvider 接口定义见 documentation/docs/guides-concepts/data-fetching/data-provider-interface.md。loading 状态loading id variables?.id isPending——只有当当前按钮的id恰好等于正在执行中的删除请求的id时该按钮才进入 loading 状态避免列表中其他行的按钮被连带转圈。权限与表单联动useButtonCanAccess负责访问控制检查setWarnWhen(false)则在删除前重置未保存更改警告useWarnAboutChange防止删除操作被表单未保存提示拦截。确认框文本的 i18n 测试佐证useDeleteButton的测试位于 packages/core/src/hooks/button/delete-button/index.spec.tsx其中两个用例直接验证了文案机制默认无 i18nProvider时返回label: Delete、confirmOkLabel: Delete、confirmTitle: Are you sure?、cancelLabel: Cancel传入自定义i18nProvider后buttons.delete、buttons.confirm、buttons.cancel三个 key 会被翻译成自定义文案如 Delete (i18n)。也就是说只需在 i18n 资源中覆盖buttons.delete/buttons.confirm/buttons.cancel即可全局本地化删除按钮与确认框的文字。组件的单元测试入口Ant Design 侧对DeleteButton的测试通过复用refinedev/ui-tests的通用按钮测试套件完成见 packages/antd/src/components/buttons/delete/index.spec.tsximport { buttonDeleteTests } from refinedev/ui-tests; import { DeleteButton } from ./; describe(Delete Button, () { buttonDeleteTests.bind(this)(DeleteButton); });这意味着删除按钮的渲染、确认交互、禁用/隐藏、权限等行为都由统一的测试契约保障也侧面印证了各 UI 框架Ant Design、MUI、Mantine、Chakra UI的删除按钮行为一致。配套能力批量删除与相关参考批量删除场景当需要支持表格多选批量删除时文档建议使用useDeleteMany而非逐行DeleteButton。仓库示例 examples/table-antd-use-delete-many/src/pages/posts/list.tsx 展示了完整做法通过rowSelection收集选中的行点击 Delete Selected 按钮后调用useDeleteMany一次性删除多个 ID成功后清空选中态const { mutate, mutation: { isPending: deleteManyIsLoading }, } useDeleteManyIPost(); const deleteSelectedItems () { mutate( { resource: posts, ids: selectedRowKeys.map(String), }, { onSuccess: () { setSelectedRowKeys([]); }, }, ); };该示例同时展示了把EditButton、ShowButton等与删除按钮组合放进操作列搭配hideText的常见布局。快速自定义使用 Refine CLI 进行 Swizzle文档特别提示你可以通过Refine CLI对这个组件进行 swizzle把组件源码弹出到你的项目中以便深度自定义。Refine CLI 的安装与使用方法见 documentation/docs/packages/cli/index.md。swizzle 之后你可以直接修改弹出副本的 JSX 结构、样式或默认行为同时保留原有 props 接口。小结DeleteButton把危险操作需二次确认这一最佳实践固化成了开箱即用的组件外层由 Ant Design 的Popconfirm兜底确认交互内层逻辑由useDeleteButton串联useDelete→ dataProviderdeleteOne的完整调用链并天然支持路由参数推断、i18n 文案、访问控制和三种 mutation 模式。日常使用中只需记住几个要点列表页记得传recordItemId跨资源操作记得传resource需要权限控制时配置accessControlProvider并结合hideIfUnauthorized追求极简布局时用hideText。若需要批量删除则切换到useDeleteMany若要深度定制组件本身可用 Refine CLI 进行 swizzle。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考