react-admin - SimpleRestProvider 空资源
问题描述
我正在尝试将 Cockpit CMS 用作休息后端,但是我无法理解休息提供者和资源的逻辑。显然我们首先调用 GET_LIST - 它工作正常,资源参数等已设置。但它也使用 emtpy 资源调用 GET_MANY。如您所见,我替换了
url = `${apiUrl}/${resource}?${stringify(query)}`;
和
url = `${apiUrl}/collections/get/testing?token=SOMETOKEN&filter[_id]=5e2037a536383609f00001cc`;
这不会产生错误,但我不明白为什么在 get_many 调用中资源是 emtpy/undefined。
应用程序.js:
import React from 'react';
import authProvider from './cockpitAuthProvider';
import { Admin, Resource, ListGuesser } from 'react-admin';
import simpleRestProvider from './simpleRestProviderlistCollections';
const App = () => (
<Admin authProvider={authProvider} dataProvider={simpleRestProvider('http://someurl/cockpit-0.9.3/api')}>
<Resource name="testing" list={ListGuesser} />
</Admin>
);
export default App;
simpleRestProviderlistCollections.js:
import { stringify } from 'query-string';
import {
fetchUtils,
GET_LIST,
GET_ONE,
GET_MANY,
GET_MANY_REFERENCE,
CREATE,
UPDATE,
UPDATE_MANY,
DELETE,
DELETE_MANY,
} from 'react-admin';
**
* Maps react-admin queries to a simple REST API
*
* The REST dialect is similar to the one of FakeRest
* @see https://github.com/marmelab/FakeRest
* @example
* GET_LIST => GET http://my.api.url/posts?sort=['title','ASC']&range=[0, 24]
* GET_ONE => GET http://my.api.url/posts/123
* GET_MANY => GET http://my.api.url/posts?filter={ids:[123,456,789]}
* UPDATE => PUT http://my.api.url/posts/123
* CREATE => POST http://my.api.url/posts
* DELETE => DELETE http://my.api.url/posts/123
*/
export default (apiUrl, httpClient = fetchUtils.fetchJson) => {
/**
* @param {String} type One of the constants appearing at the top if this file, e.g. 'UPDATE'
* @param {String} resource Name of the resource to fetch, e.g. 'posts'
* @param {Object} params The data request params, depending on the type
* @returns {Object} { url, options } The HTTP request parameters
*/
const convertDataRequestToHTTP = (type, resource, params) => {
let url = '';
console.log(`convertDataRequestToHTTP ${resource}`);
const options = {};
switch (type) {
case GET_LIST: {
console.log(`convertDataRequestToHTTP GET_LIST ${resource}`);
const { page, perPage } = params.pagination;
const { field, order } = params.sort;
const query = {
sort: JSON.stringify([field, order]),
range: JSON.stringify([
(page - 1) * perPage,
page * perPage - 1,
]),
filter: JSON.stringify(params.filter),
};
//added a / before ?
//url = `${apiUrl}/${resource}/get/?${stringify(query)}`;
url = `${apiUrl}/collections/get/${resource}?token=SOMETOKEN`;
break;
}
case GET_ONE:
url = `${apiUrl}/${resource}/${params.id}`;
break;
case GET_MANY: {
console.log(`convertDataRequestToHTTP GET_MANY ${resource}`);
const query = {
filter: JSON.stringify({ id: params.ids }),
};
//url = `${apiUrl}/${resource}?${stringify(query)}`;
url = `${apiUrl}/collections/get/testing?token=SOMETOKEN&filter[_id]=5e2037a536383609f00001cc`;
break;
}
case GET_MANY_REFERENCE: {
console.log("convertDataRequestToHTTP GET_MANY_REFERENCE");
const { page, perPage } = params.pagination;
const { field, order } = params.sort;
const query = {
sort: JSON.stringify([field, order]),
range: JSON.stringify([
(page - 1) * perPage,
page * perPage - 1,
]),
filter: JSON.stringify({
...params.filter,
[params.target]: params.id,
}),
};
url = `${apiUrl}/${resource}?${stringify(query)}`;
break;
}
case UPDATE:
url = `${apiUrl}/${resource}/${params.id}`;
options.method = 'PUT';
options.body = JSON.stringify(params.data);
break;
case CREATE:
url = `${apiUrl}/${resource}`;
options.method = 'POST';
options.body = JSON.stringify(params.data);
break;
case DELETE:
url = `${apiUrl}/${resource}/${params.id}`;
options.method = 'DELETE';
break;
default:
throw new Error(`Unsupported fetch action type ${type}`);
}
return { url, options };
};
/**
* @param {Object} response HTTP response from fetch()
* @param {String} type One of the constants appearing at the top if this file, e.g. 'UPDATE'
* @param {String} resource Name of the resource to fetch, e.g. 'posts'
* @param {Object} params The data request params, depending on the type
* @returns {Object} Data response
*/
const convertHTTPResponse = (response, type, resource, params) => {
const { headers, json } = response;
switch (type) {
case GET_LIST:
var jnew = json.entries
return {
data: jnew.map(resource => ({ ...resource, id: resource._id }) ),
total: 1,
};
case GET_MANY_REFERENCE:
var jnew = json.entries
console.log(json)
return {
data: jnew.map(resource => ({ ...resource, id: resource._id }) ),
total: 1,
};
case CREATE:
return { data: { ...params.data, id: json._id } };
default:
return { data: json };
}
};
/**
* @param {string} type Request type, e.g GET_LIST
* @param {string} resource Resource name, e.g. "posts"
* @param {Object} payload Request parameters. Depends on the request type
* @returns {Promise} the Promise for a data response
*/
return (type, resource, params) => {
// simple-rest doesn't handle filters on UPDATE route, so we fallback to calling UPDATE n times instead
if (type === UPDATE_MANY) {
return Promise.all(
params.ids.map(id =>
httpClient(`${apiUrl}/${resource}/${id}`, {
method: 'PUT',
body: JSON.stringify(params.data),
})
)
).then(responses => ({
data: responses.map(response => response.json),
}));
}
// simple-rest doesn't handle filters on DELETE route, so we fallback to calling DELETE n times instead
if (type === DELETE_MANY) {
return Promise.all(
params.ids.map(id =>
httpClient(`${apiUrl}/${resource}/${id}`, {
method: 'DELETE',
})
)
).then(responses => ({
data: responses.map(response => response.json),
}));
}
const { url, options } = convertDataRequestToHTTP(
type,
resource,
params
);
console.log(resource)
console.log(options)
console.log(url)
return httpClient(url, options).then(response =>
convertHTTPResponse(response, type, resource, params)
);
};
};
这似乎也是问题/解决方案的问题:如何在 react-admin 中拥有多个 dataProviders 的正确方法是什么?
因为如果我按照解决方案的方式去做,我也会得到错误:
TypeError: dataProviderMapping.dataProvider is not a function
由于空资源。
我也试过这个:https://github.com/marmelab/react-admin/blob/master/packages/ra-data-json-server/src/index.ts实现应该像这样工作:
getList GET http://my.api.url/posts?_sort=title&_order=ASC&_start=0&_end=24&title=bar
getMany 获取http://my.api.url/posts/123,获取http://my.api.url/posts/456,获取http://my.api.url/posts/789
但是,在我的情况下,它会产生http://my.api.url/s/123(因为资源是空的)
Api 返回: http: //192.168.0.163/cockpit-0.9.3/api/collections/get/testing ?token=TOKEN
{"fields":{"bla":{"name":"bla","type":"text","localize":false,"options":[]},"blup":{"name":"blup","type":"text","localize":false,"options":[]}},"entries":[{"bla":"dgfhs","blup":"sdgfh","_mby":"5ddc222d36383611fa00025a","_by":"5ddc222d36383611fa00025a","_modified":1579169696,"_created":1579169696,"_id":"5e2037a036383609f0000270"},{"bla":"sgdf","blup":"sdfg","_mby":"5ddc222d36383611fa00025a","_by":"5ddc222d36383611fa00025a","_modified":1579169701,"_created":1579169701,"_id":"5e2037a536383609f00001cc"}],"total":2}
{
"fields": {
"bla": {
"name": "bla",
"type": "text",
"localize": false,
"options": []
},
"blup": {
"name": "blup",
"type": "text",
"localize": false,
"options": []
}
},
"entries": [
{
"bla": "sgdf",
"blup": "sdfg",
"_mby": "5ddc222d36383611fa00025a",
"_by": "5ddc222d36383611fa00025a",
"_modified": 1579169701,
"_created": 1579169701,
"_id": "5e2037a536383609f00001cc"
}
],
"total": 1
}
解决方案
推荐阅读
- python - 如何使用变量作为其他文件中的名称来调用函数
- javascript - GitHub Pages + Jekyll + Bootstrap + CDN 问题
- java - 有没有一种方法可以在不创建另一个数组的情况下排除数组中的非重复数字?
- drop-down-menu - 无法让动态下拉列表在 Kendo 网格行中工作
- r - 尝试在 R 中运行 kNN 时收到 coercionNAs 引入的错误 NA?
- knockout.js - Knockoutjs如何使用三元运算符添加必需的属性进行输入
- c++ - Windows 生物识别服务在调用 WinBioCaptureSample 时循环运行 SensorAdapterStartCapture
- google-sheets - 为什么 INDIRECT 函数返回 1?
- sap - 更新 IoT 目标时 SAP Web IDE 登录失败
- amazon-web-services - ECS Fargate + 网络负载均衡器健康检查