news 2026/9/11 16:11:57

Refine Simple REST 数据提供器实战指南:REST API 集成、URL 约定与源码级定制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Refine Simple REST 数据提供器实战指南:REST API 集成、URL 约定与源码级定制

Refine Simple REST 数据提供器实战指南:REST API 集成、URL 约定与源码级定制

【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine

本文以 Refine 官方数据提供器@refinedev/simple-rest为主线,系统讲解如何在 Refine v5 项目中快速接入符合 json-server 设计约定的 REST API,覆盖安装、配置、分页/排序/过滤的 Query 序列化、HTTP 方法与自定义 Header,并结合仓库源码与单元测试揭示其底层实现原理。读完本文,你将能独立完成一个 REST 数据源的接入、调优,并在 API 不匹配时通过swizzle命令定制专属数据提供器。

Simple REST 是什么

@refinedev/simple-rest是 Refine 生态中面向标准 REST API 的数据提供器(data provider)实现。它的 URL 设计与查询参数约定建立在 json-server 的基础之上:资源名直接拼在apiUrl之后,分页、排序、过滤分别通过_start/_end_sort/_orderfield_operator等约定参数表达,并依靠响应头x-total-count返回数据总数。

该包导出一个工厂函数dataProvider(apiUrl, httpClient),完整实现了 RefineDataProvider接口中的核心方法,包括getListgetManygetOnecreateupdatedeleteOne,以及customgetApiUrl。它的定位是"开箱即用、按需定制":先用它快速跑通数据流,当后端 API 不遵循标准设计时,再基于它做局部或整体定制。

从仓库的 packages/simple-rest/package.json 可以看到,该包当前版本为6.0.1,运行时依赖仅axiosquery-string,以@refinedev/core@^5.0.0作为 peer dependency,并要求 Node.js >= 20。

安装

在项目根目录执行:

npm install @refinedev/simple-rest # 或使用 pnpm pnpm add @refinedev/simple-rest

安装后,数据提供器即作为dataProvider属性接入<Refine>组件。

快速开始

dataProvider工厂函数接受两个参数:

  • apiUrl(必填):API 的基础地址,所有请求都会拼接到该地址之下;
  • httpClient(可选):自定义 axios 实例,用于在请求层统一处理认证、错误拦截、Token 刷新等逻辑;不传时使用包内置的默认实例。
import { Refine } from "@refinedev/core"; import dataProvider from "@refinedev/simple-rest"; import axios from "axios"; // 自定义 axios 实例(可选),可用于注入认证头、统一错误处理 const httpClient = axios.create(); const App = () => { return ( <Refine // httpClient 为可选参数,不传则使用内置实例 dataProvider={dataProvider("https://api.fake-rest.refine.dev", httpClient)} /* ... */ /> ); };

注意:这里传给<Refine>的是dataProvider(...)的调用结果(一个方法对象),而不是函数本身;apiUrl需替换为你自己的后端地址。

URL 设计约定

数据提供器的每个方法都按标准 REST 风格构造 URL,下表来自官方文档 documentation/docs/data/packages/simple-rest/index.md,可直接作为后端路由设计对照:

MethodURLQuery ParametersBody
getListapiUrl/resourcepagination,sorters,filters
getOneapiUrl/resource/id
getManyapiUrl/resourceid
createapiUrl/resourcevariables
updateapiUrl/resource/idvariables
deleteOneapiUrl/resource/iddata: variables

apiUrl = "https://api.fake-rest.refine.dev"、资源posts为例:

  • getList请求GET /posts
  • getOneupdatedeleteOne请求GET/PATCH/DELETE /posts/1
  • getMany请求GET /posts?id=1&id=2(ids 数组被query-string序列化为重复的id参数);
  • create请求POST /posts,请求体携带variables
  • deleteOne的请求体通过 axios 配置的data字段携带variables(详见下文源码解析)。

分页、排序与过滤:Query 序列化源码解析

getList是逻辑最复杂的方法,其 URL 的构建逻辑集中在 packages/simple-rest/src/provider.ts,分页、排序、过滤最终都会落到 URL 的查询参数上。

分页:_start_end

从源码看,getListpagination的解构默认值为currentPage = 1pageSize = 10mode = "server"。当mode === "server"(默认值)时:

query._start = (currentPage - 1) * pageSize; query._end = currentPage * pageSize;

即第 1 页请求?_start=0&_end=10,第 2 页请求?_start=10&_end=20。如果传pagination: { mode: "off" },则不分页,不追加这两个参数。测试 packages/simple-rest/test/getList/index.spec.ts 还专门验证了当过滤、排序、分页都为空时,请求 URL 上不会出现多余的?字符。

排序:_sort_order

排序由 packages/simple-rest/src/utils/generateSort.ts 生成:把多个排序字段分别用逗号拼接进_sort_order。例如对id升序、title降序排序,会得到?_sort=id,title&_order=asc,desc。当sorters为空时该函数返回undefinedgetList不会追加排序参数。

过滤:操作符映射

过滤条件由 packages/simple-rest/src/utils/generateFilter.ts 与 packages/simple-rest/src/utils/mapOperator.ts 配合生成。mapOperator把 Refine 的逻辑操作符映射为 json-server 风格的后缀:

Refine 操作符序列化后的查询参数后缀说明
eq(无后缀)直接以字段名作为参数
ne_ne不等于
gte_gte大于等于
lte_lte小于等于
contains_like模糊匹配
其他操作符(无后缀)按字段名直接传值

例如过滤category.id = 1,最终请求为GET /posts?category.id=1status ne "draft"则序列化为status_ne=draft。其余操作符(gtltinbetweennullstartswith等)在mapOperator中均返回空字符串,直接以field=value形式传递——这是"简单 REST"的取舍:只承诺最常见的操作符映射,特殊需求交给custom方法或 swizzle 定制。

generateFilter还有两个值得注意的行为:

  1. field === "q"的过滤条件被原样保留为q参数,用于全文搜索场景;
  2. operatororand时会直接抛出错误,提示"不支持该操作符,可创建自定义数据提供器"。这意味着 Simple REST 默认不支持逻辑组过滤,需要该能力时应考虑定制。

总数:x-total-count响应头

getList返回的total来自响应头x-total-count+headers["x-total-count"]强制转为数字);当该头缺失时回退为data.length。因此后端需要在响应头中返回真实总数,前端才能正确渲染分页。

custom 方法

custom方法用于调用非标准端点,其实现(packages/simple-rest/src/provider.ts)会把传入的sortersfiltersquery依次序列化拼接进 URL,并根据method选择请求方式:put/post/patch携带 payload 体,delete通过 axios 的data配置携带 payload,其余情况默认走GET

默认 HTTP 方法与自定义

每个数据提供器方法默认使用如下 HTTP 方法:

MethodHTTP Method
getListGET
getOneGET
getManyGET
createPOST
updatePATCH
deleteOneDELETE

注意update默认是PATCH(部分更新)而非PUT(整体替换),这符合 json-server 的设计习惯。

如果后端要求某个方法使用不同动词,无需改源码,只需在调用 hook 时通过meta.method覆盖:

import { useUpdate } from "@refinedev/core"; const { mutate } = useUpdate(); mutate({ resource: "posts", id: 1, values: { title: "New title", }, meta: { method: "put", }, });

从源码看,meta.method的值被分为两类:getList/getMany/getOne限定为"get" | "delete" | "head" | "options"create/update/deleteOne限定为"post" | "put" | "patch"。也就是说,如果你为update传入meta.method: "put",请求会变为PUT /posts/1,body 携带variables

传递自定义 Header

部分接口需要在单次请求级别附加认证或业务头,可以通过meta.headers传入,它会透传给 axios 请求配置:

import { useOne } from "@refinedev/core"; useOne({ resource: "posts", id: 1, meta: { headers: { "X-Custom-Header": "Custom header value", }, }, });

headers只作用于本次调用,适合临时性的跨租户标识、调试头等场景;全局性的认证头更推荐在自定义httpClient的拦截器里统一注入。

错误处理与默认 axios 实例

Simple REST 内置了一个默认 axios 实例,实现在 packages/simple-rest/src/utils/axios.ts 中。它在响应拦截器的错误分支里把原始错误规整为 Refine 的HttpError结构:

const customError: HttpError = { ...error, message: error.response?.data?.message, statusCode: error.response?.status, };

即从响应体提取message、从响应对象提取statusCode,统一 reject 出去,方便 Refine 的useShowuseForm等 hook 展示错误信息。当你的后端错误结构不同(比如 message 字段在error对象里),或需要携带 Authorization 头时,就应传入自定义httpClient

import axios from "axios"; const httpClient = axios.create({ baseURL: "https://api.example.com", headers: { Authorization: `Bearer ${token}` }, }); httpClient.interceptors.response.use( (response) => response, (error) => { // 统一错误映射、401 跳转登录等 return Promise.reject(error); }, );

用 swizzle 定制数据提供器

当后端 REST API 偏离 simple-rest 的约定(例如分页用page/limit、过滤用其他参数名)时,官方推荐用 Refine CLI 的swizzle命令把数据提供器源码"复制"到项目内自行修改:

  1. 在项目目录运行:

    npm run refine swizzle
  2. 从列表中选择@refinedev/simple-rest

  3. 编辑生成在项目中的rest-data-provider/index.ts,按需修改getList的分页参数、mapOperator的操作符映射等;

  4. 将定制后的数据提供器传给<Refine>

    import { Refine } from "@refinedev/core"; import { dataProvider } from "./rest-data-provider"; const App = () => { return ( <Refine dataProvider={dataProvider("https://api.fake-rest.refine.dev")} /* ... */ /> ); };

swizzle 出来的rest-data-provider保留了provider.ts的完整结构,你可以在复制品上直接改_start/_end的拼法、替换query-string序列化逻辑,而无需修改 node_modules 中的包文件。仓库内 packages/simple-rest/src/provider.ts、packages/simple-rest/src/utils/generateFilter.ts、packages/simple-rest/src/utils/mapOperator.ts 就是最直接的定制参考模板。

测试验证:约定即契约

仓库为 Simple REST 配备了完整的 vitest 测试(packages/simple-rest/test),既是回归保障,也是行为契约文档:

  • packages/simple-rest/test/getList/index.spec.ts 验证了getListhttps://api.fake-rest.refine.dev的请求:默认分页返回total为 1000;带category.id = 1过滤时返回 17 条;排序、过滤组合生效;空条件下 URL 不带?
  • packages/simple-rest/test/utils/mapOperator.spec.ts 覆盖了negteltecontains等映射结果,并断言其他操作符(含and/or/between/null/startswith等)均返回空字符串——这进一步印证了"只承诺常见操作符"的设计边界;
  • 此外还有createupdatedeleteOnegetOnecustom等目录下的 mock 与 spec,展示了每个方法在api.fake-rest.refine.dev上的实际请求形态与响应解析。

小结

@refinedev/simple-rest的价值在于"标准约定 + 低成本定制":对符合 json-server 风格的后端,一个工厂函数调用即可完成全部 CRUD 接入;分页、排序、过滤的参数化全部由 provider.ts 与 utils 透明处理,meta.method/meta.headers提供按请求的灵活性;遇到不匹配的 API,swizzle命令让你把实现复制进项目自由改造。接入前,建议先对照本文的 URL 与参数约定表核对后端路由,再用 测试用例 中的请求形态作为联调基线,可以显著缩短集成周期。

【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 16:09:23

SerenityOS json 命令实战指南:语法高亮、缩进美化与点分查询

SerenityOS json 命令实战指南&#xff1a;语法高亮、缩进美化与点分查询 【免费下载链接】serenity The Serenity Operating System &#x1f41e; 项目地址: https://gitcode.com/GitHub_Trending/se/serenity json 是 SerenityOS 自带的 JSON 命令行工具&#xff0c;…

作者头像 李华
网站建设 2026/9/11 16:09:18

YOLOv5火灾识别与检测系统实战:环境配置、训练与实时推理

简介&#xff1a;这是一份基于YoloV5的火灾识别与检测系统完整项目&#xff0c;面向计算机视觉、深度学习方向的在校学生、算法工程师及毕设/课设开发者&#xff0c;覆盖从数据集配置、模型训练到推理部署的完整流程&#xff0c;可快速上手目标检测与火灾区域定位。资源共130个…

作者头像 李华
网站建设 2026/9/11 16:08:11

Typst 快速安装与配置指南:5 步跑通 PDF 编译

Typst 快速安装与配置指南&#xff1a;5 步跑通 PDF 编译 【免费下载链接】typst A markup-based typesetting system that is powerful and easy to learn. 项目地址: https://gitcode.com/GitHub_Trending/ty/typst Typst 是一套把 .typ 源文件直接编译成 PDF 的标记语…

作者头像 李华
网站建设 2026/9/11 16:04:38

SSM金融终端管理系统:JSP层重梳与国密加密实践

简介&#xff1a;本资源是一套基于SSM框架的金融支付终端管理系统毕设项目&#xff0c;面向计算机专业本科生及Java全栈初学者&#xff0c;解决金融场景下支付终端统一管理、交易处理与账务审计等核心需求。压缩包含1246个文件&#xff0c;总大小16.72MB&#xff0c;其中Java源…

作者头像 李华
网站建设 2026/9/11 16:04:10

猫抓:浏览器端一站式媒体资源嗅探与下载工具

猫抓&#xff1a;浏览器端一站式媒体资源嗅探与下载工具 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 猫抓&#xff08;cat-catch&#xff09;是…

作者头像 李华