React Admin 实时数据提供者(Realtime Data Provider)接入完整指南:方法签名、内置适配器与自定义实现

发布时间:2026/9/21 4:03:36
React Admin 实时数据提供者(Realtime Data Provider)接入完整指南:方法签名、内置适配器与自定义实现 前端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 生态中ra-realtime包对dataProvider的实时化扩展要求从subscribe/unsubscribe/publish与锁相关方法的签名约定到 Supabase、API Platform、Mercure 三种开箱即用的内置适配器再到手写自定义适配器的完整示例与 Topic / Event / Lock 数据格式规范。读完本文你将能够为任意实时后端WebSocket、长轮询、GraphQL Subscription 等编写自己的实时适配器并让ListLiveUpdate、EditLive、ShowLive等实时组件正常工作。ra-realtime是 react-admin 实时协作能力的核心运行时库它采用与 CRUD 方法完全一致的adapter适配器思路实时能力并非硬编码进 UI而是通过扩展dataProvider的方法实现来接入任意实时基础设施。本文对应的完整概念与配套组件概览见 Realtime 总览文档其中涉及的ListLiveUpdate、EditLive、ShowLive组件及useGetListLive、useGetOneLive等 Hook 的用法可参阅对应文档页。一、实时方法及其签名约定要让 react-admin 的实时组件正常工作你的dataProvider必须额外实现三个新方法subscribe(topic, callback)—— 订阅指定 topic当该 topic 上有事件发布时回调callbackunsubscribe(topic, callback)—— 取消订阅参数必须与subscribe时完全一致同一函数引用publish(topic, event)—— 向指定 topic 发布事件可选因为在多数架构中发布动作发生在服务端。这三个方法应当返回一个已 resolve 的空 Promise表示该动作已被实时总线确认接收。此外若要支持 react-admin 的记录锁lock功能防止多人并发编辑同一记录dataProvider还需额外实现 4 个方法lock(resource, { id, identity, meta })unlock(resource, { id, identity, meta })getLock(resource, { id, meta })getLocks(resource, { meta })从源码层面看这一扩展机制是完全开放的在 packages/ra-core/src/types.ts 中react-admin 的DataProvider类型是一个对象类型除getList、getOne、getMany、update、create、delete等标准 CRUD 方法外还声明了[key: string]: any索引签名。这意味着subscribe、publish、lock等任意自定义方法都可以合法地挂载在dataProvider上并被 react-admin 的应用层正常调用。而 useDataProvider 会从DataProviderContext中取出你传入Admin dataProvider{...}的实例因此只要把增强后的实时dataProvider传给Admin任何组件都能通过useDataProvider()访问这些实时方法。二、内置适配器Supabasera-realtime内置了基于 Supabase Realtime 能力的增强函数addRealTimeMethodsBasedOnSupabase。该适配器订阅 Supabase 的Postgres Changes事件并将其转换为ra-realtime期望的事件格式。你只需把原有的supabaseDataProvider来自ra-supabase和supabaseClient来自supabase/supabase-js传入即可import { createClient } from supabase/supabase-js; import { supabaseDataProvider } from ra-supabase; import { addRealTimeMethodsBasedOnSupabase, ListLiveUpdate } from react-admin/ra-realtime; import { Admin, Resource, DataTable, List, EmailField } from react-admin; const supabaseClient createClient( process.env.SUPABASE_URL, process.env.SUPABASE_ANON_KEY ); const dataProvider supabaseDataProvider({ instanceUrl: process.env.SUPABASE_URL, apiKey: process.env.SUPABASE_ANON_KEY, supabaseClient }); const realTimeDataProvider addRealTimeMethodsBasedOnSupabase({ dataProvider, supabaseClient, }); export const App () ( Admin dataProvider{realTimeDataProvider} Resource namesales list{SaleList} / /Admin ); const SaleList () ( List DataTable DataTable.Col sourceid / DataTable.Col sourcefirst_name / DataTable.Col sourcelast_name / DataTable.Col sourceemail field{EmailField} / /DataTable ListLiveUpdate / /List );示例中的ListLiveUpdate是实时列表刷新组件当其他用户新增、更新或删除记录时当前列表会自动刷新。注意Supabase 默认不启用实时功能需要手动开启。有两种方式在 Supabase Dashboard 的Replication复制页面勾选需要同步的表用SQL Editor执行如下 SQL创建并维护supabase_realtimepublicationbegin; -- remove the supabase_realtime publication drop publication if exists supabase_realtime; -- re-create the supabase_realtime publication with no tables create publication supabase_realtime; commit; -- add a table to the publication alter publication supabase_realtime add table sales; alter publication supabase_realtime add table contacts; alter publication supabase_realtime add table contactNotes;addRealTimeMethodsBasedOnSupabase接受以下参数PropRequiredTypeDefaultDescriptiondataProviderRequiredDataProvider-要被增强为实时方法的基础 dataProvidersupabaseClientRequiredSupabaseClient-Supabase JS 客户端实例自定义 JWT Token 的提示如果你希望自行签发 token 以在 RLS 策略中校验自定义 claim那么使用addRealTimeMethodsBasedOnSupabase时必须在创建supabaseClient时同时为 Realtime 的headers和params传入apikey字段。具体做法请参考 Supabase 官方文档中关于自定义 tokencustom tokens的说明。三、内置适配器API PlatformAPI Platform 场景下ra-realtime提供addRealTimeMethodsBasedOnApiPlatform函数它基于 API Platform 的Mercure Hub实现实时能力。该函数需要三个附加参数Mercure Hub 的 URL、用于向 Hub 鉴权的 JWT token、以及 API Platform 使用的 topic 基础 URL末尾不要带斜杠import { DataTable, EditButton, List, ListProps } from react-admin; import { HydraAdmin, ResourceGuesser, FieldGuesser, hydraDataProvider, } from api-platform/admin; import { ListLiveUpdate, addRealTimeMethodsBasedOnApiPlatform, } from react-admin/ra-realtime; const dataProvider hydraDataProvider(https://localhost:8443); const dataProviderWithRealtime addRealTimeMethodsBasedOnApiPlatform( // 原始 dataProvider由 API Platform 提供的 hydra data provider dataProvider, // API Platform 的 Mercure Hub URL https://localhost:1337/.well-known/mercure, // 用于向 API Platform Mercure Hub 鉴权的 JWT token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InB1Ymxpc2giOlsiKiJdfX0.obDjwCgqtPuIvwBlTxUEmibbBf0zypKCNzNKP7Op2UM, // API Platform 使用的 topic URL末尾不带斜杠 https://localhost:8443 ); const App () ( HydraAdmin entrypointhttps://localhost:8443 dataProvider{dataProviderWithRealtime} ResourceGuesser namegreetings list{GreetingsList} / /HydraAdmin ); // 连接 greetings 列表的示例 const GreetingsList () ( List DataTable DataTable.Col sourcename field{FieldGuesser} / DataTable.Col EditButton / /DataTable.Col /DataTable ListLiveUpdate / /List );注意示例中的 JWT 是一个演示用 token实际项目中应通过后端签发并动态获取切勿硬编码在客户端代码中。四、内置适配器Mercure如果你的后端走的是通用 Mercure hub不依赖 API Platform可以使用addRealTimeMethodsBasedOnMercure。它接受原始dataProvider、Mercure hub 的 URL、以及 JWT token 三个参数import { addRealTimeMethodsBasedOnMercure } from react-admin/ra-realtime; const dataProviderWithRealtime addRealTimeMethodsBasedOnMercure( // 原始 dataProvider dataProvider, // Mercure hub URL http://path.to.my.api/.well-known/mercure, // 用于向 Mercure Hub 鉴权的 JWT token eyJhbGciOiJIUzI1NiJ9.eyJtZXJjdXJlIjp7InB1Ymxpc2giOlsiKiJdLCJzdWJzY3JpYmUiOlsiKiJdfX0.SWKHNF9wneXTSjBg81YN5iH8Xb2iTf_JwhfUY5Iyhsw ); const App () ( Admin dataProvider{dataProviderWithRealtime}{/* ... */}/Admin );示例 JWT 的mercureclaim 中声明了publish: [*]和subscribe: [*]即允许发布与订阅所有 topic。生产环境中应遵循最小权限原则按实际业务限定 topic 范围。五、编写自定义适配器当实时传输走的是 WebSocket、长轮询long polling、GraphQL Subscription 等其他协议时你需要自己在dataProvider上实现subscribe、unsubscribe与publish。下面是一个基于局部变量的内存实现——这也是ra-realtime在自身测试中使用的示例let subscriptions []; const dataProvider { // 常规 dataProvider 方法getList、getOne 等 // ... subscribe: async (topic, subscriptionCallback) { subscriptions.push({ topic, subscriptionCallback }); return Promise.resolve({ data: null }); }, unsubscribe: async (topic, subscriptionCallback) { subscriptions subscriptions.filter( subscription subscription.topic ! topic || subscription.subscriptionCallback ! subscriptionCallback ); return Promise.resolve({ data: null }); }, publish: (topic, event) { if (!topic) { return Promise.reject(new Error(missing topic)); } if (!event.type) { return Promise.reject(new Error(missing event type)); } subscriptions.map( subscription topic subscription.topic subscription.subscriptionCallback(event) ); return Promise.resolve({ data: null }); }, };这个示例清晰地展示了三个关键点subscribe/unsubscribe必须配对使用且参数一致unsubscribe依赖 topic 与回调函数引用双重匹配来移除订阅因此组件卸载时必须传入与订阅时相同的函数引用否则无法成功退订这正是 react-admin 文档中useEffect清理函数里要保存原callback引用的原因。publish应做参数校验缺少topic或缺少event.type时应当返回 rejected 的 Promise尽早暴露错误。返回结构统一所有方法最终返回Promise.resolve({ data: null })符合 react-admin 对 dataProvider 返回结构的期待。调试阶段你还可以利用addRealTimeMethodsInLocalBrowser提供的默认 console 日志输出直接在浏览器控制台观察实时组件的事件行为验证订阅、发布链路是否正确。六、Topic 与事件Event格式你或许已经注意到所有 dataProvider 实时方法的第一个参数都是topic。topic 就是标识某个实时通道的字符串在聊天应用里它可以用来区分不同房间在 CRUD 场景里它可以用来标识与某条记录相关的变更。ra-realtime的大多数组件围绕 CRUD 逻辑展开因此它会订阅两个特殊命名的 topicresource/[name]—— 整个资源的变更通道resource/[name]/[id]—— 单条记录的变更通道。对于你自己的业务事件可以随意选用任何 topic 字符串。event是从发布者发给订阅者的消息它是一个 JavaScript 对象必须包含type和payload两个字段。最小示例如下{ type: created, payload: New message, }对于 CRUD 操作ra-realtime期望事件的type取值为created、updated、deleted三者之一详下一节。七、CRUD 事件规范ra-realtime与 react-admin 深度集成其核心逻辑围绕记录的创建、更新、删除展开。为了让列表实时刷新、让EditLive/ShowLive感知变更你的实时后端必须按下述规范发布事件创建记录时广播到资源级 topic携带created事件{ topic: resource/${resource}, event: { type: created, payload: { ids: [id]}, }, }更新记录时需要同时向记录级 topic 与资源级 topic 发布updated事件因为列表视图订阅的是资源级 topic而编辑/详情视图订阅的是记录级 topic{ topic: resource/${resource}/id, event: { type: updated, payload: { ids: [id]}, }, } { topic: resource/${resource}, event: { type: updated, payload: { ids: [id]}, }, }删除记录时与更新类似同样需要记录级与资源级两个 topic 各发一次deleted事件{ topic: resource/${resource}/id, event: { type: deleted, payload: { ids: [id]}, }, } { topic: resource/${resource}, event: { type: deleted, payload: { ids: [id]}, }, }注意上述resource与id均为模板变量实际发布时应替换为真实值payload.ids统一使用数组即使只涉及一条记录。这些事件会触发ListLiveUpdate刷新对应列表、EditLive/ShowLive更新正在查看的页面详见 ListLiveUpdate、EditLive、ShowLive。八、锁Lock格式与锁相关方法锁用于防止多位用户并发编辑同一条记录。一个锁对象保存了被锁的记录、锁定者身份以及加锁时间典型结构如下{ resource: posts, recordId: 123, identity: julien, createdAt: 2023-01-02T21:36:35.133Z, }dataProvider.getLock()与dataProvider.getLocks()应当返回上述结构的锁对象单个或数组。而两个变更类方法dataProvider.lock()与dataProvider.unlock()则期望以下参数resource资源名如postsparams一个对象包含id记录 id如123identity锁定者的身份标识字符串或数字均可如julien实际项目中可以是认证 tokenmeta会原样转发给 dataProvider 的附加对象可选。在 react-admin 应用中配合useLock、useUnlock、useGetLock、useGetLocks、useLockOnCall、useLockOnMount等 Hook 使用即可实现「进入编辑页自动加锁 / 离开时解锁 / 他人编辑时表单禁用」的完整协作编辑体验相关用法见 useLock、useLockOnMount、useLockCallbacks、useGetLock、useGetLocks。九、基于 lock 资源的锁实现如果你不想为锁单独对接一套存储ra-realtime还提供addLocksMethodsBasedOnALockResource函数它把锁的读写翻译为对一个普通locks资源的 CRUD 操作dataProvider.getLocks()调用会被翻译成dataProvider.getList(locks)dataProvider.lock()调用会被翻译成dataProvider.create(locks)。这个lock资源上的每条记录应包含如下字段{ id: 123, identity: Toad, resource: people, recordId: 18, createdAt: 2020-09-29 10:20 }需要说明的是identity与createdAt的具体格式取决于你的后端 API以上只是约定俗成的示例。在 react-admin 应用中使用它的方式与实时适配器完全一致——只需增强原始 dataProvider 后传入Adminimport { Admin } from react-admin; import { addLocksMethodsBasedOnALockResource } from react-admin/ra-realtime; const dataProviderWithLocks addLocksMethodsBasedOnALockResource( dataProvider // 原始 dataProvider ); const App () ( Admin dataProvider{dataProviderWithLocks}{/* ... */}/Admin );十、在组件中直接调用 dataProvider 实时方法将增强后的实时dataProvider传给Admin之后你可以在任意 React 组件中通过useDataProvider()Hook 直接调用这些实时方法。react-admin 的useDataProvider实现见 packages/ra-core/src/dataProvider/useDataProvider.ts从DataProviderContext取出实例并对调用做统一的响应格式校验因此实时方法同样会经由这一代理被调用。下面是一个实时展示messagestopic 消息的组件挂载时订阅卸载时退订收到事件后追加到列表import React, { useState } from react; import { useDataProvider, useNotify } from react-admin; const MessageList () { const notify useNotify(); const [messages, setMessages] useState([]); const dataProvider useDataProvider(); useEffect(() { const callback event { // event 形如 // { // topic: messages, // type: created, // payload: New message, // } setMessages(messages [...messages, event.payload]); notify(New message); }; // 挂载时订阅 messages topic dataProvider.subscribe(messages, callback); // 卸载时退订 return () dataProvider.unsubscribe(messages, callback); }, [setMessages, notify, dataProvider]); return ( ul {messages.map((message, index) ( li key{index}{message}/li ))} /ul ); };再来看一个向messagestopic 发布事件的按钮——该 topic 上的所有订阅者都会执行各自的回调import React from react; import { useDataProvider, useNotify } from react-admin; const SendMessageButton () { const dataProvider useDataProvider(); const notify useNotify(); const handleClick () { dataProvider .publish(messages, { type: created, payload: New message }) .then(() notify(Message sent)); }; return Button onClick{handleClick}Send new message/Button; };实践建议你通常不需要直接调用publish()。大多数实时后端会在数据发生变化时自动发布事件所以上面这个按钮示例是虚构的教学场景。现实中一个典型的SendMessageButton只需调用dataProvider.create(messages)由 API 完成「创建消息」与「向实时总线发布created事件」两件事。这也再次印证了前文的原则实时发布是服务端职责客户端适配器主要负责订阅与消费。十一、更进一步了解实时功能的整体架构、Publish/Subscribe 机制、实时通知、菜单徽标与安装方式见 Realtime 总览文档学习如何从零编写一个支持实时方法的 dataProvider见 编写自定义 dataProvider查阅 react-admin 支持的 dataProvider 列表见 DataProvider 列表深入理解数据获取流程中实时钩子的定位见 数据获取指南 与 DataProvider 实时能力。接入实时能力后多个用户可以在同一张列表、同一个编辑页面上协同工作且不会丢失彼此的修改——这正是ra-realtime与本文所述实时 dataProvider 规范共同提供的价值。赞分享前端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数据提供者(Data Provider)机制解析深入React Admin数据提供者 Data Provider 机制解析 React Admin的数据提供者Data Provider是其架构设计的核心前端UI组件react-admin 自定义 Data Provider 编写指南方法契约、参数协议与完整 REST/GraphQL 实现react admin 自定义 Data Provider 编写指南方法契约、参数协议与完整 REST/GraphQL 实现 导读 本指南基于 react前端UI组件为 react-admin 编写自定义 Data Provider方法契约、错误规范与 REST / GraphQL 完整实现为 react admin 编写自定义 Data Provider方法契约、错误规范与 REST / GraphQL 完整实现 react admin 的 A前端UI组件上一篇【亲测免费】让你的任务栏萌起来RunCat_for_windows新手入门指南及常见问题解决下一篇Celestia核心功能解析从太阳系到深空天体的完整教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考