如何将NodeJS后端数据传输对接至react-admin管理面板
react-admin 对接现有Node+Sequelize+PostgreSQL后端方案
你不用重构现有已经跑通的业务接口,react-admin的DataProvider本质就是一层请求适配层,核心作用是把框架内置的操作翻译成你后端能识别的请求,再把后端返回的数据转换成react-admin要求的格式,对接成本很低。
后端侧适配(可选,不想改后端就全在DataProvider层做转换)
你现有接口的增删改查逻辑完全不用动,只需要给列表类接口补几个通用查询参数的解析,用Sequelize的原生查询能力就能直接对接:
- 分页参数:如果接收到
_page(页码,从1开始)、_perPage(每页条数)参数,直接计算offset为(_page - 1) * _perPage,传给findAndCountAll方法的offset和limit选项即可 - 排序参数:如果接收到
_sortField(排序字段)、_sortOrder(排序方向ASC/DESC),直接传给查询的order选项 - 筛选参数:如果接收到
_filter参数(JSON序列化的筛选对象),解析后根据业务需求拼到where条件里,模糊查询就用Op.like,精确匹配就直接传值 - 接口返回格式统一调整为:
- 列表接口返回
{ "data": [/* 当前页记录数组,每条必须带唯一id字段(直接用主键就行)*/], "total": /* 符合条件的总记录数,取findAndCountAll返回的count值 */ } - 单条增删改查接口返回
{ "data": /* 对应操作的记录对象 */ } - 请求出错直接返回对应HTTP状态码和错误信息即可,react-admin会自动捕获提示
- 列表接口返回
如果你不想改现有接口的参数规则、返回结构,完全可以跳过这步,所有参数转换、返回值格式调整都在前端DataProvider层完成,维护成本更低。
前端侧编写自定义DataProvider
不用找第三方适配包,自己写适配层也就几十行代码,比强行改第三方包适配你的业务接口灵活得多。
- 在react-admin项目中新建
dataProvider.js文件,基础实现如下:
import { fetchUtils } from 'react-admin'; // 改成你自己的Node后端接口根地址,开发环境跨域直接在打包工具里配代理即可 const API_BASE = '/api'; const httpClient = fetchUtils.fetchJson; // react-admin自带的请求封装,自动处理鉴权头、错误状态码 export default { getList: async (resource, params) => { // resource就是<Resource>组件上配置的name属性,对应后端接口路径,比如users、orders const { page, perPage } = params.pagination; const { field, order } = params.sort; const query = new URLSearchParams({ _page: page, _perPage: perPage, _sortField: field, _sortOrder: order, _filter: JSON.stringify(params.filter), }); const res = await httpClient(`${API_BASE}/${resource}?${query}`); return { data: res.json.data, total: res.json.total, }; }, getOne: async (resource, params) => { const res = await httpClient(`${API_BASE}/${resource}/${params.id}`); return { data: res.json.data }; }, getMany: async (resource, params) => { // 批量查询场景,比如关联字段下拉选项加载,后端支持id批量查询就传ids,不支持可以后续补逻辑 const query = new URLSearchParams({ ids: params.ids.join(',') }); const res = await httpClient(`${API_BASE}/${resource}?${query}`); return { data: res.json.data }; }, getManyReference: async (resource, params) => { // 关联列表查询,比如查看某用户下的所有订单,逻辑和getList基本一致,多传关联字段条件 const { page, perPage } = params.pagination; const { field, order } = params.sort; const query = new URLSearchParams({ _page: page, _perPage: perPage, _sortField: field, _sortOrder: order, _filter: JSON.stringify({ ...params.filter, [params.target]: params.id, }), }); const res = await httpClient(`${API_BASE}/${resource}?${query}`); return { data: res.json.data, total: res.json.total }; }, create: async (resource, params) => { const res = await httpClient(`${API_BASE}/${resource}`, { method: 'POST', body: JSON.stringify(params.data), }); return { data: res.json.data }; }, update: async (resource, params) => { const res = await httpClient(`${API_BASE}/${resource}/${params.id}`, { method: 'PUT', body: JSON.stringify(params.data), }); return { data: res.json.data }; }, delete: async (resource, params) => { const res = await httpClient(`${API_BASE}/${resource}/${params.id}`, { method: 'DELETE', }); return { data: res.json.data }; }, // 批量操作方法,暂时没做对应后端接口可以先留空实现,后续补功能再改 deleteMany: async (resource, params) => { const res = await httpClient(`${API_BASE}/${resource}/bulk-delete`, { method: 'POST', body: JSON.stringify({ ids: params.ids }), }); return { data: res.json.data }; }, updateMany: async (resource, params) => { const res = await httpClient(`${API_BASE}/${resource}/bulk-update`, { method: 'PUT', body: JSON.stringify({ ids: params.ids, data: params.data }), }); return { data: res.json.data }; }, };
- 在项目入口
App.jsx中引入自定义的DataProvider,传给Admin组件即可:
import { Admin, Resource } from 'react-admin'; import dataProvider from './dataProvider'; // 引入你写的各业务模块的列表、编辑、创建页组件 import UserList from './pages/UserList'; function App() { return ( <Admin dataProvider={dataProvider}> <Resource name="users" list={UserList} /> {/* 其他业务资源比如orders、products配置逻辑和users一致,name属性对应后端接口路径 */} </Admin> ); } export default App;
对接踩坑提醒
- Sequelize查询返回的模型实例不要直接返给前端,一定要调用
.toJSON()转成普通对象,否则会带大量模型内部属性,导致react-admin字段解析异常 - 所有返回给react-admin的记录必须带唯一的
id字段,如果你的业务表主键名不是id,要么在后端返回时把主键值映射为id,要么在DataProvider拿到响应数据后遍历做一次字段映射 - 如果你现有接口的参数名、返回结构和示例不一致,直接在DataProvider里调整参数拼接、响应转换逻辑就行,比如你后端分页参数是
pageNum/pageSize,就把query里对应的键名改掉即可,完全不用动后端代码 - 开发环境的跨域问题直接在Vite/Webpack等构建工具里配置接口代理就行,不用专门修改后端CORS配置适配开发环境
内容的提问来源于stack exchange,提问作者kd12345
相关产品推荐
相关产品推荐

