如果我有多个不同的REST API后端(单独的应用程序执行不同的事情),我想要一个能够对由这些不同后端管理的实体进行CRUD的UI(基于react-admin的)应用程序,我很好奇是否可以联系react-admin来做到这一点。
我想象的不是这个(单一/全局dataProvider):
const App = () => (
<Admin dataProvider={simpleRestProvider('http://path.to.foo.api')}>
<Resource name="foos" list={FooList} />
</Admin>
);
我们可以做这样的事情(特定于资源的dataProviders):
const App = () => (
<Admin >
<Resource name="foos" list={FooList}
dataProvider={simpleRestProvider('http://path.to.foo.api')} />
<Resource name="bars" list={BarList}
dataProvider={simpleRestProvider('http://path.to.bar.api')} />
</Admin>
);
无论如何,如果你对如何在react-admin中对多个后端做REST的建议,我非常感激。
答案 0 :(得分:5)
否,但是您可以拥有一个超级dataProvivder,它将根据资源选择适当的一个。像这样:
const dataProviders = [
{ dataProvider: simpleRestProvider('http://path.to.foo.api'), resources: ['foos'] },
{ dataProvider: simpleRestProvider('http://path.to.bar.api'), resources: ['bars'] },
];
export default (type, resource, params) => {
const dataProvider = dataProviders.find(dp => dp.resources.includes(resource));
return dataProvider(type, resource, params);
}
答案 1 :(得分:3)
在README of recent ra release (3.4.1)中,有一节(扩展数据提供程序(文件上传示例))提到:“ ...将两个后端的两个数据提供程序组合到单个对象中...”。您可以编写带有分支的包装器,以中继到其他提供程序的实现。在示例的顶部添加真实数据提供程序的示例是:
// new file dataProvider/super.js
import simpleRestProvider from 'ra-data-simple-rest';
import delayedDataProvider from './rest'
const realDataProvider = simpleRestProvider('http://real_world_url/');
const myDataProvider = {
...delayedDataProvider,
getList: (resource, params) => {
console.log(resource)
if (["customers", "reviews", "commands"].includes(resource)) {
// resources for the demo
return delayedDataProvider.getList(resource, params)
} else {
// your own resources
return realDataProvider.getList(resource, params)
}
},
};
export default myDataProvider;
,然后将延迟的DataProvider替换为上面的myDataProvider
// file dataProvider/index.js
case 'graphql':
return import('./graphql').then(factory => factory.default());
default:
- return import('./rest').then(provider => provider.default);
+ return import('./super').then(provider => provider.default);
免责声明:我和以前的帖子有同样的错误“提供程序不起作用...”
答案 2 :(得分:2)
React Admin 3为dataProvider使用了新界面,并且所有答案似乎仅适用于React Admin 2。
这是我在React Admin 3上所做的工作
class CompositeDataProvider {
constructor(dataProviders) {
this.dataProviders = dataProviders;
}
_delegate(name, resource, params) {
const { dataProvider } = this.dataProviders.find((dp) =>
dp.resources.includes(resource)
);
return dataProvider[name](resource, params);
}
getList(resource, params) {
return this._delegate("getList", resource, params);
}
getOne(resource, params) {
return this._delegate("getOne", resource, params);
}
getMany(resource, params) {
return this._delegate("getMany", resource, params);
}
getManyReference(resource, params) {
return this._delegate("getManyReference", resource, params);
}
create(resource, params) {
return this._delegate("create", resource, params);
}
update(resource, params) {
return this._delegate("update", resource, params);
}
updateMany(resource, params) {
return this._delegate("updateMany", resource, params);
}
delete(resource, params) {
return this._delegate("delete", resource, params);
}
deleteMany(resource, params) {
return this._delegate("deleteMany", resource, params);
}
}
export default CompositeDataProvider;
您可以通过以下方式使用它:
const dataProvider = new compositeDataProvider([
{
dataProvider: jsonServerProvider("https://jsonplaceholder.typicode.com"),
resources: ["posts", "users"],
},
{
dataProvider: simpleRestProvider("http://path.to.bar.api"),
resources: ["bars"],
},
]);
它仍然是准系统,但是它给您一个可以改进的想法。
答案 3 :(得分:1)
我从@Gildas Garcia 的回答中得到了这个想法。非常感谢@Gildas Garcia。但是您的代码仅适用于 React admin 版本 2,在版本 3 及更高版本中,我需要一些习惯才能使其工作。这是我的解决方案
// ... others import
import {
fetchUtils,
GET_LIST,
GET_ONE,
CREATE,
UPDATE,
UPDATE_MANY,
DELETE,
GET_MANY,
GET_MANY_REFERENCE,
} from 'react-admin';
const dataProviders = [
{
dataProvider: simpleRestProvider('http://localhost:3000'),
resources: ['users'],
},
{
dataProvider: simpleRestProvider('http://localhost:3002'),
resources: ['roles'],
},
{
dataProvider: customJSONDataProvider('http://localhost:3003'),
resources: ['permissions'],
},
];
export default (type, resource, params) => {
const dataProviderMapping = dataProviders.find((dp) =>
dp.resources.includes(resource));
const mappingType = {
[GET_LIST]: 'getList',
[GET_ONE]: 'getOne',
[GET_MANY]: 'getMany',
[GET_MANY_REFERENCE]: 'getManyReference',
[CREATE]: 'create',
[UPDATE]: 'update',
[UPDATE_MANY]: 'updateMany',
[DELETE]: 'delete',
};
return dataProviderMapping.dataProvider[mappingType[type]](resource, params);
};
答案 4 :(得分:0)
您可以自定义资源,选择要使用的api。 一位管理员只有一个dataProvider。
<Admin
dataProvider={superDataProvider}
/>
但是您可以这样做:
import superDataProvider from './dataProviderFactory';
以下是我的代码,您可以参考
import dataProviderRuby from './dataProvider'; //handle ruby dataProvider
import dataProviderJava from './dataProviderForJava';// handle java dataProvider
import { rubyClient, javaClient } from './apolloClient';//custom two diff client one will fetch ruby service ,other will java
const IsOmsResource = resource => {
const omsReource = [
'markets',
'regions',
'countries',
'states',
'items',
'salesOrganizations',
];
return omsReource.some(ele => ele === resource);
}; //those resource will fetch data from java service others will go to ruby
const rubyDataProvider = async (type, resource, params) => {
const provider = await dataProviderRuby({
client: rubyClient,
});
return provider(type, resource, params);
};
const javaDataProvider = async (type, resource, params) => {
const provider = await dataProviderJava({
client: javaClient,
});
return provider(type, resource, params);
};
const superDataProvider = (type, resource, params) => {
if (IsOmsResource(resource)) {
console.log('当前Java', resource);
return javaDataProvider(type, resource, params);
}
console.log('当前ruby', resource);
return rubyDataProvider(type, resource, params);
};
export default superDataProvider;
以下是“ ./apolloClient”
import ApolloClient from 'apollo-client';
import { createHttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { setContext } from 'apollo-link-context';
const httpLinkRuby = createHttpLink({
uri: '/graphql',
});
const httpLinkJava = createHttpLink({
uri: '/oms-graphql',
});
const authLink = setContext((_, { headers }) => {
const token = localStorage.getItem('token');
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : '',
},
};
});
export const rubyClient = new ApolloClient({
link: httpLinkRuby,
cache: new InMemoryCache(),
});
export const javaClient = new ApolloClient({
link: authLink.concat(httpLinkJava),
cache: new InMemoryCache(),
});