Back

使用 React Admin 构建数据驱动的应用

使用 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 Queryreact-hook-formreact-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 围绕九个核心方法构建:getListgetOnegetManygetManyReferencecreateupdateupdateManydeletedeleteMany。每个方法接收一个请求对象并返回一个 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-restra-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)
}

构建列表和编辑视图

一旦你的 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.

OpenReplay