ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

refine v3 教程:掌握 Chakra UI `<Edit>` 编辑页组件全属性用法与源码原理

refine v3 教程:掌握 Chakra UI `<Edit>` 编辑页组件全属性用法与源码原理 refine v3 教程掌握 Chakra UIEdit编辑页组件全属性用法与源码原理【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refineEdit是 refine 框架在 Chakra UI 集成中提供的编辑页布局组件用于构建posts/edit/:id这类数据编辑页面。它本身不包含业务逻辑但内置了刷新、列表跳转、删除、保存等按钮与面包屑、标题、加载态等页面骨架能力。本篇指南以documentation/versioned_docs/version-3.xx.xx/api-reference/chakra-ui/components/basic-views/edit.md为核心逐项讲解Edit的每一个属性title、saveButtonProps、canDelete、resource、recordItemId、mutationMode、dataProviderName、goBack、isLoading、breadcrumb、wrapperProps、headerProps、contentProps、headerButtons、headerButtonProps、footerButtons、footerButtonProps并结合仓库源码packages/chakra-ui/src/components/crud/edit/index.tsx解释其底层实现帮助你在实际项目中精准定制编辑页面。Edit是什么页面布局而非业务逻辑在 refine 中Edit组件的作用是为编辑页面提供布局它不替你做表单、不替你拉取数据而是把编辑页常见的页面骨架标题、面包屑、返回按钮、头部操作按钮、主体内容区、底部保存/删除按钮、加载态统一封装起来让你把精力集中在表单本身。从源码可以看出它的组成结构。在 packages/chakra-ui/src/components/crud/edit/index.tsx 中Edit的渲染结构由以下几层组成最外层Box带positionrelative与背景色接收wrapperPropsisLoading为真时覆盖全页的居中Spinner头部Box接收headerProps左侧是面包屑 返回按钮 标题右侧是头部操作按钮区接收headerButtonProps内容区Box接收contentPropsisLoading时透明度降为 0.5内容就是你的表单底部按钮区Box接收footerButtonProps默认渲染DeleteButton条件渲染和SaveButton。这意味着Edit可以作为一个壳被单独使用配合pankod/refine-react-hook-form的useForm把保存、加载等状态绑定上去。最小可用示例与 useForm 搭配原文档给出的完整编辑页示例见documentation/versioned_docs/version-3.xx.xx/api-reference/chakra-ui/components/basic-views/edit.md展示了最典型的用法——把useForm返回的formLoading、saveButtonProps交给Edit用register绑定表单字段import { Refine } from pankod/refine-core; import { useSelect } from pankod/refine-core; import { useForm } from pankod/refine-react-hook-form; import { Edit, FormControl, FormErrorMessage, FormLabel, Input, Select, } from pankod/refine-chakra-ui; interface IPost { id: number; title: string; content: string; status: published | draft | rejected; category: { id: number }; } const PostEdit: React.FC () { const { refineCore: { formLoading, queryResult }, saveButtonProps, register, formState: { errors }, resetField, } useFormIPost(); const { options } useSelect({ resource: categories, defaultValue: queryResult?.data?.data.category.id, queryOptions: { enabled: !!queryResult?.data?.data.category.id }, }); useEffect(() { resetField(category.id); }, [options]); return ( Edit isLoading{formLoading} saveButtonProps{saveButtonProps} FormControl mb3 isInvalid{!!errors?.title} FormLabelTitle/FormLabel Input idtitle typetext {...register(title, { required: Title is required })} / FormErrorMessage{${errors.title?.message}}/FormErrorMessage /FormControl {/* status 与 category 字段同理此处省略 */} /Edit ); }; const App () { return ( Refine routerProvider{routerProvider} dataProvider{dataProvider(https://api.fake-rest.refine.dev)} notificationProvider{RefineChakra.notificationProvider()} resources{[ { name: posts, edit: PostEdit, list: DummyListPage, }, ]} / ); };要点saveButtonProps直接来自useForm点击底部保存按钮即提交表单isLoading绑定formLoading数据加载期间整个页面显示 Spinner 并禁用按钮下拉选项用useSelect加载分类资源并通过defaultValuequeryOptions.enabled先拿到当前记录的category.id再加载选项避免无谓请求。属性详解title 与页面标题定制titletitle用于自定义编辑页头部标题。若不传组件默认使用 Edit 前缀 资源名单数形式例如资源posts会显示Edit post。从源码看标题渲染逻辑位于 packages/chakra-ui/src/components/crud/edit/index.tsx传false则不渲染标题传字符串/数字渲染为Heading ash3 sizelg传 React 节点则直接渲染什么都不传时使用translate(${identifier}.titles.edit, Edit ...)查找多语言文案回退到Edit {getUserFriendlyName(resource, singular)}其中资源标签优先取resource.meta.label。自定义标题示例import { Edit, Heading } from pankod/refine-chakra-ui; const PostEdit: React.FC () { return ( Edit title{Heading sizelgCustom Title/Heading} pRest of your page here/p /Edit ); };saveButtonPropsEdit默认自带一个保存按钮。通过saveButtonProps可以把该按钮的任何属性透传给 Chakra UI 的按钮组件如colorScheme、size、disabled等。源码中保存按钮的组装逻辑在 packages/chakra-ui/src/components/crud/edit/index.tsxsaveButtonProps由isLoading为真时自动加disabled与用户传入的saveButtonPropsFromProps合并而成最终传给SaveButton。点击保存按钮即提交表单。Edit saveButtonProps{{ colorScheme: red }} pRest of your page here/p /Edit更详细的SaveButton用法可参考 保存按钮文档。属性详解canDelete 与 deleteButtonPropscanDelete决定编辑页是否显示删除按钮。若资源本身声明了canDelete属性refine 默认会加上删除按钮你也可以通过deleteButtonProps定制它。点击删除按钮时执行的是 dataProvider 提供的deleteOne方法。源码中删除按钮的可见性判断packages/chakra-ui/src/components/crud/edit/index.tsxconst isDeleteButtonVisible canDelete ?? (!!resource?.meta?.canDelete || deleteButtonPropsFromProps);也就是说三选一即可显示删除按钮显式传canDelete、资源meta.canDelete为真、或传了deleteButtonProps。删除成功后组件会通过go({ to: goListPath })跳回列表页源码第 110-112 行。结合权限控制可以实现仅管理员可删除import { Edit } from pankod/refine-chakra-ui; import { usePermissions } from pankod/refine-core; const PostEdit: React.FC () { const { data: permissionsData } usePermissions(); return ( Edit canDelete{permissionsData?.includes(admin)} deleteButtonProps{{ colorScheme: orange }} pRest of your page here/p /Edit ); };上例中authProvider.getPermissions返回admin时才会出现删除按钮。usePermissions的完整用法见 权限 Hook 文档DeleteButton的详细用法见 删除按钮文档。仓库中的测试用例也验证了这套判断逻辑见 packages/chakra-ui/src/components/crud/edit/index.spec.tsx分别覆盖了资源canDelete: true/false与组件canDelete属性交叉组合、以及传入deleteButtonProps即显示按钮的四种场景。属性详解resource 与 recordItemIdresourceEdit默认从路由读取资源名如/posts/edit/:id中的posts。但在自定义页面Custom Page中路由没有资源信息此时需要用resource属性显式指定。import { Refine } from pankod/refine-core; import { Layout, Edit } from pankod/refine-chakra-ui; import routerProvider from pankod/refine-react-router-v6; import dataProvider from pankod/refine-simple-rest; const CustomPage: React.FC () { return ( Edit resourcecategories pRest of your page here/p /Edit ); }; const App: React.FC () { return ( Refine routerProvider{{ ...routerProvider, routes: [ { element: CustomPage /, path: /custom/:id, }, ], }} Layout{Layout} dataProvider{dataProvider(https://api.fake-rest.refine.dev)} resources{[{ name: posts }]} / ); };源码中通过useResourceParams({ resource: resourceFromProps })解析资源packages/chakra-ui/src/components/crud/edit/index.tsx当传入resource时会优先使用它而不是路由推断值。测试用例should render optional resource with resource propindex.spec.tsx 第 73-86 行也验证了在/custom路由下传resourceposts会渲染出 Edit Post 标题。recordItemIdEdit默认从 URL 读取记录id。当组件用在无法从 URL 读取 id 的场景自定义页面、Modal、Drawer时需要手动传recordItemId。同时要注意RefreshButton正常工作必须依赖id信息原文档专门以:::note强调而recordItemId正是把 id 交给刷新按钮的通道。源码中 id 的合并逻辑在 packages/chakra-ui/src/components/crud/edit/index.tsxconst id recordItemId ?? idFromParams;随后该id会传给RefreshButton与DeleteButton分别见第 98-103 行与第 105-117 行。典型场景——在 Modal 中使用useModalForm打开编辑弹窗import { useModalForm } from pankod/refine-react-hook-form; import { Edit, Modal, Button, ModalOverlay, ModalContent, ModalCloseButton, ModalHeader, ModalBody, } from pankod/refine-chakra-ui; const PostEdit: React.FC () { const { modal: { visible, close, show }, id, } useModalForm({ refineCoreProps: { action: edit }, }); return ( div Button onClick{() show()}Edit Button/Button Modal isOpen{visible} onClose{close} sizexl ModalOverlay / ModalContent ModalCloseButton / ModalHeaderEdit/ModalHeader ModalBody Edit recordItemId{id} pRest of your page here/p /Edit /ModalBody /ModalContent /Modal /div ); };属性详解mutationMode 与删除/保存的提交时机mutationMode决定DeleteButton执行删除时的变更模式mutation mode可选值模式行为pessimistic默认模式先请求后反馈成功后立即反映到 UIoptimistic先乐观更新 UI请求失败再回滚undoable先更新 UI在倒计时窗口内可撤销原文档给出的示例是mutationModeundoable配合canDeleteimport { Edit, Input, FormControl, FormLabel, FormErrorMessage, } from pankod/refine-chakra-ui; import { useForm } from pankod/refine-react-hook-form; const PostEdit: React.FC () { const { saveButtonProps, register, formState: { errors }, } useFormIPost(); return ( Edit mutationModeundoable canDelete saveButtonProps{saveButtonProps} FormControl mb3 isInvalid{!!errors?.title} FormLabelTitle/FormLabel Input idtitle typetext {...register(title, { required: Title is required })} / FormErrorMessage{${errors.title?.message}}/FormErrorMessage /FormControl /Edit ); };源码中mutationMode的取值优先级packages/chakra-ui/src/components/crud/edit/index.tsxconst mutationMode mutationModeFromProps ?? mutationModeContext;即组件属性优先未传时回退到useMutationMode()返回的全局上下文默认pessimistic。该模式会被注入DeleteButton的 props。若使用 undoable 模式还需要在Refine上配置notificationProvider以显示可撤销的倒计时通知。三种模式的详细机制见 变更模式高级教程。属性详解dataProviderName 多数据源切换当应用配置了多个 data provider 时Edit默认使用defaultprovider若某个编辑页需要操作其他数据源通过dataProviderName指定import { Refine } from pankod/refine-core; import { Edit } from pankod/refine-chakra-ui; import routerProvider from pankod/refine-react-router-v6; import dataProvider from pankod/refine-simple-rest; const PostEdit () { return Edit dataProviderNameother.../Edit; }; export const App: React.FC () { return ( Refine routerProvider{routerProvider} dataProvider{{ default: dataProvider(https://api.fake-rest.refine.dev/), other: dataProvider(https://other-api.fake-rest.refine.dev/), }} resources{[{ name: posts, edit: PostEdit }]} / ); };源码中dataProviderName会被传给RefreshButton与DeleteButtonpackages/chakra-ui/src/components/crud/edit/index.tsx使这两个按钮发起的请求命中正确的数据源。属性详解goBack 返回按钮定制goBack用于定制左上角返回按钮。传入false或null可完全隐藏传入任意 React 节点如图标则替换默认的IconArrowLeft /。源码实现packages/chakra-ui/src/components/crud/edit/index.tsx返回按钮是一个IconButton其点击行为依赖useBack()仅当当前action不是list时才可点击。注意源码中goBackFromProps (false || null)这个判断恒等于false false的比较因此实际隐藏判断依赖goBackFromProps是否为 falsy 值。import { Edit } from pankod/refine-chakra-ui; import { IconMoodSmile } from tabler/icons; const PostEdit: React.FC () { return ( Edit goBack{IconMoodSmile} pRest of your page here 2/p /Edit ); };属性详解isLoading 加载态isLoading控制Edit的加载状态为true时页面中央显示 Spinner、内容区透明度降为 0.5同时刷新/列表/删除/保存按钮自动加上disabled。Edit isLoading{true} pRest of your page here/p /Edit源码中 isLoading 影响三处packages/chakra-ui/src/components/crud/edit/index.tsx居中Spinner的条件渲染内容区opacity{isLoading ? 0.5 : undefined}listButtonProps、refreshButtonProps、deleteButtonProps、saveButtonProps中...(isLoading ? { disabled: true } : {})。属性详解breadcrumb 面包屑定制breadcrumb用于定制或禁用编辑页面包屑。默认使用pankod/refine-chakra-ui包内的Breadcrumb组件。传入任意 React 节点即可替换传false或null可隐藏。import { Edit, Breadcrumb, Box } from pankod/refine-chakra-ui; const PostEdit: React.FC () { return ( Edit breadcrumb{ Box borderColorblue borderStyledashed borderWidth2px Breadcrumb / /Box } pRest of your page here/p /Edit ); };源码中的取值逻辑packages/chakra-ui/src/components/crud/edit/index.tsxbreadcrumbFromProps未定义时回退到Refine组件的options.breadcrumb全局配置否则用组件属性覆盖——因此该特性可以全局统一管理。测试用例也验证了传breadcrumb{null}时面包屑不渲染index.spec.tsx 第 347-364 行。面包屑组件的完整文档见 Breadcrumb 文档全局配置见 Refine 组件 options 配置。属性详解wrapperProps / headerProps / contentProps 三层结构定制Edit的布局可以分成三层各有对应的 props且都透传给 Chakra UI 的Box因此支持所有 Box 属性如borderColor、p、bg等Props作用的层说明wrapperProps最外层容器源码中是根Box自带positionrelative、bgchakra-body-bg、borderRadiusmd、px4、py3headerProps头部容器源码中是mb3、displayflex、justifyContentspace-between、flexWrap自适应的BoxcontentProps内容容器源码中是包住children的BoxisLoading时opacity{0.5}示例——给三层都加上虚线蓝框Edit wrapperProps{{ borderColor: blue, borderStyle: dashed, borderWidth: 2px, p: 2, }} headerProps{{ borderColor: blue, borderStyle: dashed, borderWidth: 2px, }} contentProps{{ borderColor: blue, borderStyle: dashed, borderWidth: 2px, p: 2, }} pRest of your page here/p /Edit属性详解headerButtons 与 headerButtonProps 头部按钮headerButtons定制头部右侧按钮区接受两种形式直接传React.ReactNode——完全替换默认按钮传渲染函数({ defaultButtons }) React.ReactNode——保留默认按钮并追加自定义按钮。默认头部按钮包括自动保存指示器配置了autoSaveProps时、ListButton资源有 list 且未传recordItemId时与RefreshButton见 源码第 124-130 行。import { Edit, Button, HStack, Box } from pankod/refine-chakra-ui; const PostEdit: React.FC () { return ( Edit headerButtons{({ defaultButtons }) ( HStack {defaultButtons} Button colorSchemeredCustom Button/Button /HStack )} pRest of your page here/p /Edit ); };headerButtonProps则用于定制头部按钮区的外层包装 Box任何 Chakra UI Box 属性Edit headerButtonProps{{ borderColor: blue, borderStyle: dashed, borderWidth: 2px, p: 2, }} headerButtons{ Button variantoutline colorSchemegreen Custom Button /Button } pRest of your page here/p /Edit源码中渲染函数收到的参数不止defaultButtons还包括listButtonProps与refreshButtonProps源码第 157-165 行这意味着你可以在自定义头部时复刻默认按钮的全部行为。测试用例should customize default buttons with default propsindex.spec.tsx 第 366-411 行验证了通过渲染函数重组RefreshButton/ListButton/DeleteButton/SaveButton后按钮的禁用与样式属性依然正确传递。属性详解footerButtons 与 footerButtonProps 底部按钮footerButtons定制底部按钮区同样支持传节点或渲染函数。默认底部按钮为DeleteButton条件渲染SaveButton见 源码第 132-137 行。渲染函数收到的参数包括defaultButtons、deleteButtonProps与saveButtonProps。import { Edit, Button, HStack } from pankod/refine-chakra-ui; const PostEdit: React.FC () { return ( Edit footerButtons{({ defaultButtons }) ( HStack borderColorblue borderStyledashed borderWidth2px p2 {defaultButtons} Button colorSchemered variantsolid Custom Button /Button /HStack )} pRest of your page here/p /Edit ); };footerButtonProps定制底部按钮区外层包装Edit footerButtonProps{{ float: right, borderColor: blue, borderStyle: dashed, borderWidth: 2px, p: 2, }} pRest of your page here/p /Edit补充能力autoSaveProps 自动保存指示器原文档未展开介绍但源码中Edit还支持autoSaveProps属性类型定义见 packages/ui-types/src/types/crud.tsx当useForm开启refineCoreProps.autoSave.enabled后把返回的autoSaveProps传给Edit头部会出现AutoSaveIndicator展示 waiting for changes、saving...、saved、auto save failure 等状态。const EditPageWithAutoSave () { const { refineCore: { formLoading, autoSaveProps }, register, } useForm({ refineCoreProps: { action: edit, autoSave: { enabled: true }, }, }); return ( Edit autoSaveProps{autoSaveProps} {formLoading divloading.../div} input contenteditable="false">【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表