`<WithLocks>` 实战指南:在 react-admin 中通过 LocksContext 实时展示记录锁状态

发布时间:2026/9/21 22:54:20
`<WithLocks>` 实战指南:在 react-admin 中通过 LocksContext 实时展示记录锁状态 前端UI组件【免费下载链接】react-adminA frontend Framework for single-page applications on top of REST/GraphQL APIs, using TypeScript, React and Material Design项目地址https://gitcode.com/gh_mirrors/re/react-admin点击查看免费下载WithLocks是 react-admin 实时协作realtime / locks能力中的一个声明式容器组件它在挂载时调用dataProvider.getLocks()拉取当前资源的全部锁将结果放入LocksContext并订阅该资源的锁主题收到新事件后自动重新获取锁从而让锁状态在多个用户之间实时保持同步。本文基于本仓库的 WithLocks 文档结合 Realtime 文档、Realtime Data Provider 文档 与配套 Hook 文档从工作原理、安装配置、完整用法到数据结构逐层展开读完即可在列表、详情、编辑等场景中正确使用锁信息来防止并发编辑冲突。为什么需要WithLocks协作场景下的锁问题当多个用户并行处理同一批数据时例如客服团队共同处理工单会出现两类典型问题数据覆盖两人同时编辑同一条记录后保存者覆盖先保存者的修改信息滞后用户看到的界面无法及时反映这条记录此刻正被谁编辑。react-admin 的实时特性ra-realtimeEnterprise Edition 的一部分通过锁Lock机制解决这些问题。正如 Realtime 文档 所描述的用户可以主动请求锁或通过编辑资源获得锁。当资源被锁定时其他用户无法编辑它锁释放后其他用户才能再次编辑。锁机制依赖 data provider 提供lock、unlock、getLock、getLocks四个方法详见下文data provider 要求。而WithLocks正是把获取一组锁并保持实时更新这件事封装成了开箱即用的组件让你无需自己管理订阅生命周期就能在任意位置读取当前资源的所有锁。工作原理挂载即取锁订阅即刷新根据 WithLocks 文档WithLocks的行为可以用三步概括挂载时取锁调用dataProvider.getLocks()获取当前资源的所有锁订阅锁主题订阅当前资源对应的 locks 主题事件驱动刷新每当收到新事件就重新获取一次锁保证LocksContext中的数据始终是最新的。其中 locks 主题 与数据提供者的事件约定相关。在 RealtimeDataProvider.md 的 Topic 与事件格式 一节中说明ra-realtime的 CRUD 组件订阅resource/[name]和resource/[name]/[id]形式的主题事件是包含type与payload字段的 JavaScript 对象例如{ type: created, payload: { ids: [id] } }。锁数据的实时刷新正是建立在这套 Pub/Sub 机制之上后端或服务端业务逻辑在锁被创建/释放时向对应主题发布事件WithLocks收到后重新拉取锁列表。注意WithLocks是 Enterprise Edition 组件托管在私有 npm registry 中使用需要有效的 Enterprise Edition 订阅见 WithLocks 文档。在本仓库的 Open Source 代码中搜索不到getLocks的 ra-core 实现符合该能力由闭源react-admin/ra-core-ee包提供的定位。安装与前提条件安装WithLocks由react-admin/ra-core-ee包导出按 WithLocks 文档 的说明安装npm install --save react-admin/ra-core-ee # 或者使用 yarn yarn add react-admin/ra-core-ee更完整的实时特性包括实时列表、实时通知、锁的各类 Hook由react-admin/ra-realtime包提供安装方式一致npm install --save react-admin/ra-realtime # or yarn add react-admin/ra-realtime这两个包都属于 React-Admin Enterprise Edition托管在私有 npm registry需要订阅 Enterprise Edition 计划才能安装见 Realtime 文档的安装章节。data provider 要求必须实现锁方法WithLocks依赖dataProvider.getLocks()。要支持锁特性data provider 除了 CRUD 方法外还必须额外实现 4 个锁方法DataProviderLive.md 与 RealtimeDataProvider.md 均有记载dataProvider.lock(resource, { id, identity, meta })dataProvider.unlock(resource, { id, identity, meta })dataProvider.getLock(resource, { id, meta })dataProvider.getLocks(resource, { meta })其中getLocks用于获取某个资源的全部锁正是WithLocks在挂载时调用的方法。这些方法应返回在实时总线确认操作后 resolve 的 Promise。若你的后端是 Supabase、API Platform 或 Mercurera-realtime提供addRealTimeMethodsBasedOnSupabase、addRealTimeMethodsBasedOnApiPlatform、addRealTimeMethodsBasedOnMercure等增强函数可以直接给普通 data provider 附加实时与锁能力其他传输方式WebSocket、长轮询、GraphQL Subscription 等则需要自己实现这些方法参考 RealtimeDataProvider.md 的 Custom Adapter 示例。另外ra-realtime还提供addLocksMethodsBasedOnALockResource将锁操作映射到普通 CRUDgetLocks变为getList(locks)lock变为create(locks)适合用一张独立的locks表来存储锁见 RealtimeDataProvider.md 的 Locks Based On A Lock Resource 一节。基本用法把WithLocks包在列表外面WithLocks 文档 给出的核心用法是用WithLocks包裹整个列表然后在列表内部通过useLocksContext()读取锁并根据锁状态自定义渲染。import { ListBase, useRecordContext } from ra-core; import { WithLocks, useLocksContext } from react-admin/ra-core-ee; import { DataTable } from your-ra-ui-library; const LockField () { const locks useLocksContext(); const record useRecordContext(); if (!record) return null; const lock locks.find(lock lock.recordId record?.id); if (!lock) return null; return spanLocked by {lock.identity}/span; }; const PostList () ( WithLocks ListBase DataTable {/* 其他列 */} DataTable.Col sourcelockStatus field{LockField} / /DataTable /ListBase /WithLocks );要点拆解useLocksContext()读取WithLocks提供的锁数组Lock[]。调用位置必须在WithLocks的子树内useRecordContext()获取当前行记录lock.recordId record.id用于判断当前记录是否被锁定lock.identity加锁者的身份标识可以直接展示在界面上例如Locked by julien锁不存在时返回null这样未锁定的记录不会渲染任何锁提示界面保持干净。Props 一览WithLocks的 props 非常精简只有一项WithLocks 文档PropRequiredTypeDefaultDescriptionchildrenRequiredReactNode在LocksContext内部渲染的组件也就是说你只需关心把哪些内容包进锁上下文锁的获取、订阅与刷新全部由组件内部完成。LocksContext 中的数据形态Lock 对象长什么样useLocksContext()返回的是一个Lock[]数组。单个锁对象的标准格式在 RealtimeDataProvider.md 的 Lock Format 一节 中有明确定义{ resource: posts, recordId: 123, identity: julien, createdAt: 2023-01-02T21:36:35.133Z, }字段说明resource资源名如postsrecordId被锁定记录的 id如123identity加锁者身份字符串或数字均可例如用户名、id 或认证 tokencreatedAt锁的获取时间ISO 时间字符串。dataProvider.getLock()与dataProvider.getLocks()应返回符合上述结构的锁对象/锁数组。而加锁、解锁方法lock、unlock的参数约定为resource资源名如postsparams对象包含id记录 id如123identity加锁者标识字符串或数字例如julien也可以是认证 tokenmeta透传给 data provider 的附加信息可选。如果使用addLocksMethodsBasedOnALockResource的locks资源方案后端锁记录还需要id字段完整结构参见 RealtimeDataProvider.md{ id: 123, identity: Toad, resource: people, recordId: 18, createdAt: 2020-09-29 10:20 }进阶实战一在数据表格中禁用编辑与删除按钮WithLocks最常见的应用场景是锁定的记录不允许他人操作。把锁数据从上下文中取出后可以像 useGetLocks 文档 中的示例那样将编辑、删除按钮置灰const MyPostGrid () { const resource useResourceContext(); const { data: locks } useGetLocks(resource); return ( DataTable bulkActionButtons{false} DataTable.Col labelTitle MyPostTitle locks{locks} / /DataTable.Col DataTable.Col labelActions alignright MyPostActions locks{locks} / /DataTable.Col /DataTable ); }; const MyPostTitle ({ locks }: { locks: Lock[] }) { const record useRecordContext(); const lock locks.find(l l.recordId record.id); return ( TextField sourcetitle / {lock ( span style{{ color: red }} { (Locked by ${lock.identity})} /span )} / ); }; const MyPostActions ({ locks }: { locks: Lock[] }) { const record useRecordContext(); const locked locks.find(l l.recordId record.id); return ( DeleteButton disabled{!!locked} / LockableEditButton disabled{!!locked} / / ); };这套逻辑与WithLocks的用法完全同构——差别只在于数据来源是useLocksContext()还是useGetLocks()。若希望取锁 实时订阅 重新拉取由组件统一管理就用WithLocks若需要在更细粒度处单独控制数据流则使用useGetLocks/useGetLocksLive等 Hook详见下文配套的锁 Hook 家族。进阶实战二列表展示锁状态 详情页自动加锁WithLocks负责读锁而锁的写加锁/解锁由配套 Hook 完成。一个完整的防并发编辑方案通常这样组合1. 列表页用WithLocks实时展示每条记录的锁定状态如上面的LockField让用户一眼看出这条正被谁编辑。2. 编辑页用LockOnMountuseLockOnMount的组件形态在挂载时锁定当前记录、卸载时自动解锁import { Edit, SimpleForm, TextInput } from react-admin; import { LockOnMount } from react-admin/ra-realtime; const PostEdit () ( Edit SimpleForm TextInput sourcetitle fullWidth / TextInput sourceheadline fullWidth multiline / TextInput sourceauthor fullWidth / LockOnMount / /SimpleForm /Edit );LockOnMount会通过authProvider.getIdentity()获取当前用户身份并自动从上下文或路由猜测resource与recordId见 LockOnMount 文档。注意如果用户带着已锁定的记录直接关闭标签页/浏览器LockOnMount会阻止导航并显示通知直到记录被解锁。3. 交互式加锁也可以让用户获得焦点时加锁Realtime 文档 的锁示例展示了useGetLockLiveuseLockOnCall的用法——先查当前锁再判断表单是否禁用最后在onFocus时请求加锁const { data: lock } useGetLockLive(tickets, { id: record.id }); const { identity } useGetIdentity(); const isFormDisabled lock lock.identity ! identity?.id; const [doLock] useLockOnCall({ resource: tickets }); // TextInput 的 onFocus 里调用 doLock()并对输入控件传入 disabled{isFormDisabled}这样列表页WithLocks只读视角、编辑页LockOnMount自动加锁、表单useLockOnCall聚焦加锁三处协同即可构成完整的协作编辑闭环。配套的锁 Hook 家族WithLocks是锁能力的一个组件入口react-admin 实时体系中还有一整套锁相关 Hook见 Realtime 文档 与 DataProviderLive.md按职责可分为类别API作用读取单条锁useGetLock调用dataProvider.getLock()获取某条记录的锁读取单条锁实时useGetLockLive获取单条锁并订阅实时更新读取全部锁useGetLocks调用dataProvider.getLocks()获取资源全部锁读取全部锁实时useGetLocksLive获取全部锁并订阅实时更新加锁 / 解锁useLock、useUnlock手动加锁、解锁自动加锁useLockOnMount、useLockOnCall挂载时加锁 / 调用时加锁选择建议只需要在列表里展示锁状态并实时刷新 → 用WithLocks声明式、最省心需要在自定义逻辑中单独管理数据流例如在列表外部取锁 → 用useGetLocks/useGetLocksLive需要锁定/解锁动作编辑页、聚焦加锁 → 用useLock/useUnlock/useLockOnMount/useLockOnCall。常见问题与注意事项必须是 Enterprise EditionWithLocks由react-admin/ra-core-ee提供私有 registry 托管需要订阅 Enterprise Edition 计划才能安装使用WithLocks 文档。data provider 必须实现锁方法WithLocks依赖getLocks若 data provider 未实现会直接报错。建议先用addRealTimeMethodsBasedOn*系列增强函数或按 RealtimeDataProvider.md 的 Custom Adapter 示例手写subscribe/unsubscribe/publish与 4 个锁方法。锁的实时性依赖后端发布事件WithLocks靠订阅锁主题 收到事件后重新getLocks()来刷新。如果后端没有在锁创建/释放时向对应主题发布事件界面锁状态不会自动更新主题与事件格式见 RealtimeDataProvider.md。身份标识要稳定锁对象中的identity与authProvider.getIdentity()返回的 id 需要能对上例如都是用户 id 或用户名否则判断是否本人持有的锁会失效。锁数据只读useLocksContext()提供的是锁的只读视图加锁、解锁请走useLock/useUnlock/useLockOnMount/useLockOnCall不要直接修改锁数组。小结WithLocks把取锁—订阅—刷新这一套复杂的实时流程收敛成一个容器组件挂载即调用dataProvider.getLocks()订阅当前资源的锁主题事件到达后自动重新拉取并将最新的Lock[]暴露给LocksContext。在列表、看板、数据表格中配合useLocksContext()即可快速实现展示谁锁定了哪条记录锁定记录禁用编辑删除等协作功能再与useGetLockLive、useLockOnMount、useLockOnCall等 Hook 组合就能搭建出完整的防并发编辑方案。相关文档与源码入口WithLocks 文档Realtime 概览Locks 章节Realtime Data Provider锁方法签名、Lock 格式、locks 资源方案DataProviderLive.md实时与锁的数据提供者要求useGetLocks Hook 文档LockOnMount 组件文档useLockOnMount Hook 文档赞分享前端UI组件【免费下载链接】react-adminA frontend Framework for single-page applications on top of REST/GraphQL APIs, using TypeScript, React and Material Design项目地址https://gitcode.com/gh_mirrors/re/react-admin点击查看免费下载相关推荐react-admin 实时协作之 useLockCallbacks锁定/解锁回调与记录锁状态管理的完整指南react admin 实时协作之 useLockCallbacks锁定/解锁回调与记录锁状态管理的完整指南 useLockCallbacks 是 react前端UI组件react-admin 记录锁状态查询useGetLock 钩子深度指南react admin 记录锁状态查询 useGetLock 钩子深度指南 useGetLock 是 react admin 企业版 ra realtime前端UI组件react-admin 实时锁机制useLockOnCall 手动触发记录锁 Hook 完整实战指南react admin 实时锁机制 useLockOnCall 手动触发记录锁 Hook 完整实战指南 useLockOnCall 是 react admin前端UI组件上一篇zyfun 跨平台视频播放器完整指南5 分钟装好本地、追剧、IPTV 直播一次全有下一篇一次搞定几十份 PDF 的批量处理PDF 补丁丁使用攻略创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考