使用 React Admin 构建数据驱动的应用
如果你曾经从零开始构建过管理后台——手动连接表格、表单、分页和 API 调用——你就会知道在编写第一行业务逻辑之前需要多少样板代码。React Admin 通过提供一个结构化框架来解决这个问题,让你能够在任何 API 之上构建 CRUD 应用。本文将介绍它的工作原理,重点关注使其后端无关且真正可复用的架构。
核心要点
- React Admin 是一个用于构建数据驱动管理后台的 React 框架,而不是 UI 模板。它通过
dataProvider抽象将数据层与 UI 层分离。 dataProvider围绕九个核心方法构建,这些方法使 React Admin 能够适配任何后端——REST、GraphQL、Supabase 或其他——使框架真正实现后端无关。- 列表和编辑视图是声明式的:你组合字段组件和输入组件,React Admin 会自动处理数据获取、分页、排序和关系解析。
- 身份验证、基于角色的访问控制和实时更新通过独立的 provider 和可选扩展来处理,保持核心框架的专注性和模块化。
React Admin 到底是什么
React Admin 不是一个 UI 模板。它是一个专门为数据驱动的管理后台和内部工具构建的 React 框架。它提供了用于列表、创建、编辑和删除记录的组件,但真正的价值在于它如何将数据层与 UI 层分离。
React Admin v5 的核心基于 React Query、react-hook-form 和 react-router。它默认使用 MUI,但并不局限于此——React Admin 支持无头(headless)使用,这意味着如果需要,你可以使用自己的组件库。
三个核心构建块:Admin、Resource 和 dataProvider
每个 React Admin 应用都从三个概念开始:
<Admin>— 将所有内容连接在一起的根组件<Resource>— 将名称映射到一组 CRUD 视图和 API 端点dataProvider— React Admin 与后端之间的适配器
import { Admin, Resource } from "react-admin"
import { dataProvider } from "./dataProvider"
import { MovieList } from "./MovieList"
import { MovieEdit } from "./MovieEdit"
const App = () => (
<Admin dataProvider={dataProvider}>
<Resource name="movies" list={MovieList} edit={MovieEdit} />
</Admin>
)
当用户导航到电影列表时,React Admin 调用 dataProvider.getList("movies", params)。当他们编辑记录时,调用 dataProvider.update("movies", params)。UI 从不直接与你的 API 通信。
React Admin dataProvider 的工作原理
dataProvider 围绕九个核心方法构建:getList、getOne、getMany、getManyReference、create、update、updateMany、delete 和 deleteMany。每个方法接收一个请求对象并返回一个 Promise,并且在需要时可以使用额外的方法扩展 provider。
const dataProvider = {
getList: async (resource, params) => {
const { page, perPage } = params.pagination
const { field, order } = params.sort
const url = `${apiUrl}/${resource}?page=${page}&perPage=${perPage}&sort=${field}&order=${order}`
const { json, headers } = await httpClient(url, { signal: params.signal })
return {
data: json,
total: parseInt(headers.get("content-range").split("/").pop(), 10),
}
},
// ...其他方法
}
React Admin 不关心你的后端是 REST、GraphQL、Supabase 还是 IndexedDB。只要每条记录都有一致的 id 字段,并且你的 dataProvider 返回预期的数据结构,它就能工作。常见后端已有预构建的适配器——ra-data-simple-rest、ra-data-graphql 等——所以你通常不需要从头编写。
处理身份验证
身份验证没有内置在 dataProvider 中。React Admin 使用独立的 authProvider 来处理登录、登出和权限检查。一个常见的模式是在登录后存储 token,并在发起请求时在 dataProvider 内读取它,但 React Admin 也支持与外部身份提供商集成。
const httpClient = (url, options = {}) => {
options.user = {
authenticated: true,
token: localStorage.getItem("token"),
}
return fetchUtils.fetchJson(url, options)
}
Discover how at OpenReplay.com.
构建列表和编辑视图
一旦你的 dataProvider 连接好,构建视图主要是声明式的。对于列表视图,React Admin 的 <Datagrid> 组件根据你组合的字段组件渲染列。需要注意的是,<Datagrid> 仍然被广泛使用,但较新版本也引入了 <DataTable> 作为更现代的替代方案。
import { List, Datagrid, TextField, DateField, ReferenceField } from "react-admin"
export const MovieList = () => (
<List>
<Datagrid rowClick="edit">
<TextField source="title" />
<DateField source="release" />
<ReferenceField source="director_id" reference="directors">
<TextField source="lastname" />
</ReferenceField>
</Datagrid>
</List>
)
<ReferenceField> 会自动调用 dataProvider.getMany("directors", ...) 来解析相关记录——无需手动获取数据。
编辑表单遵循相同的模式,使用 <Edit> 和 <SimpleForm>:
import { Edit, SimpleForm, TextInput, DateInput } from "react-admin"
export const MovieEdit = () => (
<Edit>
<SimpleForm>
<TextInput source="title" />
<DateInput source="release" />
</SimpleForm>
</Edit>
)
当你需要自定义逻辑时
对于特定资源的行为——比如在删除父记录之前删除相关记录——React Admin 提供了 withLifecycleCallbacks:
import { withLifecycleCallbacks } from "react-admin"
export const dataProvider = withLifecycleCallbacks(baseDataProvider, [
{
resource: "movies",
beforeDelete: async (params, dp) => {
const { data: reviews } = await dp.getList("reviews", {
filter: { movie_id: params.id },
pagination: { page: 1, perPage: 1000 },
sort: { field: "id", order: "DESC" },
})
await dp.deleteMany("reviews", { ids: reviews.map((r) => r.id) })
return params
},
},
])
这使你的业务逻辑保持在数据层附近,而不会分散在各个组件中。
React Admin 开箱即用不提供的功能
在你决定使用之前,有几件事值得了解:
- RBAC(细粒度的基于角色的访问控制)需要企业版模块;基本的权限检查通过
authProvider处理 - 实时更新需要兼容的实时数据 provider 和额外的设置
- 文件上传需要自定义 dataProvider 逻辑来处理
multipart/form-data
React Admin 也兼容 Next.js 等框架(包括 Pages 和 App Router),并支持默认设置之外的替代路由解决方案。
总结
React Admin 的优势在于其 dataProvider 抽象。一旦你针对 API 实现了这些核心方法,你就能获得一个功能完整的 CRUD 管理后台,具有排序、过滤、分页和关系处理功能——而无需自己构建任何这些功能。如果有适合你后端的预构建适配器,就从它开始;如果没有,就编写一个自定义的;随着应用的增长,再逐步添加身份验证和生命周期回调。
常见问题
可以。React Admin 在设计上是后端无关的。你可以使用官方的 ra-data-graphql 适配器,或编写一个自定义 dataProvider,将所需的方法映射到你的 GraphQL 查询和变更。只要每条记录包含一致的 id 字段,并且你的 provider 返回预期的响应结构,React Admin 就能正常工作,无论后端是什么。
React Admin 提供了引用组件,如 ReferenceField 和 ReferenceInput,它们通过你的 dataProvider 自动获取相关记录。例如,ReferenceField 调用 dataProvider.getMany 将外键解析为显示值。你在组件树中声明关系,React Admin 在后台处理数据获取和缓存。
开源版本通过 authProvider 支持基本的身份验证和简单的权限检查。对于细粒度的基于角色的访问控制,例如根据角色隐藏字段或限制操作,你需要企业版 RBAC 模块。尽早评估你的权限需求,以决定免费版本是否满足你的需求。
可以。React Admin 默认使用 MUI,但支持无头使用,这意味着你可以用自己的组件库替换整个 UI 层。你也可以自定义 MUI 主题、覆盖单个组件,或构建完全自定义的视图,同时仍然使用 React Admin 的 hooks 进行数据获取、表单处理和路由。
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.