react-admin - React Admin 中默认排序、分页参数名称和逻辑不一致
问题描述
我有一个简单的前端 react-admin 应用程序,带有 Flask API,我正在尝试在我的 API 中实现排序、过滤和分页。
我正在使用数据提供者 ra-data-json-server,根据这个规范,我必须使用“_sort”、“_start”和“_end”参数(带有下划线)来实现它。
但是,当我查看我的 Front 应用程序执行的 GET 查询时,排序和分页将类似于:
https://balbla.com/#/users?filter=%7B%7D&order=ASC&page=1&perPage=10&sort=roles
这与那里的文档一致https://marmelab.com/react-admin/DataProviders.html
所以我很困扰,因为:
- 参数名称不同(下划线)
- 分页逻辑完全不同(结束和开始与页码和页长)。
我错过了什么还是确实存在不一致之处?执行哪一个?对我来说,最简单的方法是让我的后端适应实际的 Front 查询格式,但这不是文档。
谢谢
解决方案
一开始我也和你有同样的困惑,然后我遇到了 ra-data-json-server 的源代码。它实现了 _sort、_order、_start 和 _end。首先,您需要在 API 中实现排序和分页。我会建议你在下面使用这个 ra-data-json-server 数据提供者:
import { stringify } from "query-string";
import { fetchUtils } from "ra-core";
/**
* Maps react-admin que`enter code here`ries to a json-server powered REST API
*
* @see https://github.com/typicode/json-server
*
* @example
*
* getList => GET http://my.api.url/posts?_sort=title&_order=ASC&_start=0&_end=24
* getOne => GET http://my.api.url/posts/123
* getManyReference => GET http://my.api.url/posts?author_id=345
* getMany => GET http://my.api.url/posts/123, GET http://my.api.url/posts/456, GET http://my.api.url/posts/789
* create => POST http://my.api.url/posts/123
* update => PUT http://my.api.url/posts/123
* updateMany => PUT http://my.api.url/posts/123, PUT http://my.api.url/posts/456, PUT http://my.api.url/posts/789
* delete => DELETE http://my.api.url/posts/123
*
* @example
*
* import React from 'react';
* import { Admin, Resource } from 'react-admin';
* import jsonServerProvider from 'ra-data-json-server';
*
* import { PostList } from './posts';
*
* const App = () => (
* <Admin dataProvider={jsonServerProvider('http://jsonplaceholder.typicode.com')}>
* <Resource name="posts" list={PostList} />
* </Admin>
* );
*
* export default App;
*/
var __assign =
(this && this.__assign) ||
function () {
__assign =
Object.assign ||
function (t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
export default (function (apiUrl, httpClient) {
if (httpClient === void 0) {
httpClient = fetchUtils.fetchJson;
}
return {
getList: function (resource, params) {
var _a = params.pagination,
page = _a.page,
perPage = _a.perPage;
var _b = params.sort,
field = _b.field,
order = _b.order;
var query = __assign(
__assign({}, fetchUtils.flattenObject(params.filter)),
{
_sort: field,
_order: order,
_start: (page - 1) * perPage + 1,
_end: page * perPage,
}
);
var url = apiUrl + "/" + resource + "?" + stringify(query);
return httpClient(url).then(function (_a) {
var headers = _a.headers,
json = _a.json;
if (!headers.has("x-total-count")) {
throw new Error(
"The X-Total-Count header is missing in the HTTP Response. The jsonServer Data Provider expects responses for lists of resources to contain this header with the total number of results to build the pagination. If you are using CORS, did you declare X-Total-Count in the Access-Control-Expose-Headers header?"
);
}
return {
data: json,
total: parseInt(headers.get("x-total-count").split("/").pop(), 10),
};
});
},
getOne: function (resource, params) {
return httpClient(apiUrl + "/" + resource + "/" + params.id).then(
function (_a) {
var json = _a.json;
return {
data: json,
};
}
);
},
getMany: function (resource, params) {
var query = {
id: params.ids,
};
var url = apiUrl + "/" + resource + "?" + stringify(query);
return httpClient(url).then(function (_a) {
var json = _a.json;
return { data: json };
});
},
getManyReference: function (resource, params) {
var _a;
var _b = params.pagination,
page = _b.page,
perPage = _b.perPage;
var _c = params.sort,
field = _c.field,
order = _c.order;
var query = __assign(
__assign({}, fetchUtils.flattenObject(params.filter)),
((_a = {}),
(_a[params.target] = params.id),
(_a._sort = field),
(_a._order = order),
(_a._start = (page - 1) * perPage),
(_a._end = page * perPage),
_a)
);
var url = apiUrl + "/" + resource + "?" + stringify(query);
return httpClient(url).then(function (_a) {
var headers = _a.headers,
json = _a.json;
if (!headers.has("x-total-count")) {
throw new Error(
"The X-Total-Count header is missing in the HTTP Response. The jsonServer Data Provider expects responses for lists of resources to contain this header with the total number of results to build the pagination. If you are using CORS, did you declare X-Total-Count in the Access-Control-Expose-Headers header?"
);
}
return {
data: json,
total: parseInt(headers.get("x-total-count").split("/").pop(), 10),
};
});
},
update: function (resource, params) {
return httpClient(apiUrl + "/" + resource + "/" + params.id, {
method: "PUT",
body: JSON.stringify(params.data),
}).then(function (_a) {
var json = _a.json;
return { data: json };
});
},
// json-server doesn't handle filters on UPDATE route, so we fallback to calling UPDATE n times instead
updateMany: function (resource, params) {
return Promise.all(
params.ids.map(function (id) {
return httpClient(apiUrl + "/" + resource + "/" + id, {
method: "PUT",
body: JSON.stringify(params.data),
});
})
).then(function (responses) {
return {
data: responses.map(function (_a) {
var json = _a.json;
return json.id;
}),
};
});
},
create: function (resource, params) {
return httpClient(apiUrl + "/" + resource, {
method: "POST",
body: JSON.stringify(params.data),
}).then(function (_a) {
var json = _a.json;
return {
data: __assign(__assign({}, params.data), { id: json.id }),
};
});
},
delete: function (resource, params) {
return httpClient(apiUrl + "/" + resource + "/" + params.id, {
method: "DELETE",
}).then(function (_a) {
var json = _a.json;
return { data: json };
});
},
// json-server doesn't handle filters on DELETE route, so we fallback to calling DELETE n times instead
deleteMany: function (resource, params) {
return Promise.all(
params.ids.map(function (id) {
return httpClient(apiUrl + "/" + resource + "/" + id, {
method: "DELETE",
});
})
).then(function (responses) {
return {
data: responses.map(function (_a) {
var json = _a.json;
return json.id;
}),
};
});
},
};
});
推荐阅读
- pine-script - 在 pine 脚本中同时添加止损和获利
- c++ - 二叉搜索树中的打印功能问题
- c++ - 如何简写非交换乘法?
- mysql - 添加 OFFSET 时 MySQL 查询不会返回任何行
- php - 如何以相同的日期时间从 phpmyadmin 获取值?
- python - 在另一列中搜索值并获取相应的值 python
- amazon-web-services - 在 S3 中自动创建文件夹
- javascript - 我可以使用 npm 链接来附加 React 组件吗?
- r - 从R中的列中查找下一个大于日期的日期
- sql - SQL - 为 B 列中缺少的每个不同元素的 A 列中的每个不同元素插入值 = 0 的行