在 react-admin 中拥有多个 dataProvider 的正确方法是什么?

Jav*_* C. 8 reactjs react-admin

我正在尝试在 react-admin 项目中使用多个数据提供者,但出现错误:

Warning: Missing translation for key: "dataProvider is not a function"
function.console.(anonymous function) @ index.js:1452
Run Code Online (Sandbox Code Playgroud)

我有我App.js这样的:

import React from 'react';
import { render } from 'react-dom';
import { Admin, Resource } from 'react-admin';
import dataProviders from './service/dataproviders';
import UserList1,  from './users1';
import UserList2,  from './users2';

const App = () => (
  render(
    <Admin dataProvider={dataProviders}>
      <Resource name="users1" list={UserList1} />
      <Resource name="users2" list={UserList2} />
    </Admin>,
    document.getElementById('root'),
  )
);

export default App;
Run Code Online (Sandbox Code Playgroud)

我有dataproviders.js文件:

import simpleRestProvider from 'ra-data-simple-rest';

const dataProviders = [
  { dataProvider: simpleRestProvider('http://path.to.foo.api1'), resources: ['users1'] },
  { dataProvider: simpleRestProvider('http://path.to.foo.api2'), resources: ['users2'] },
];

export default (type, resource, params) => {
  const dataProvider = dataProviders.find(dp => dp.resources.includes(resource));
  return dataProvider(type, resource, params);
};
Run Code Online (Sandbox Code Playgroud)

正确的方法是怎样的?

我检查了这个帖子:

react-admin 中可以有多个 dataProviders 吗?

Gil*_*cia 5

您不是在调用dataProvider您找到的对象,而是从数组中调用映射对象。你可以像这样修复它:

import simpleRestProvider from 'ra-data-simple-rest';

const dataProviders = [
  { dataProvider: simpleRestProvider('http://path.to.foo.api1'), resources: ['users1'] },
  { dataProvider: simpleRestProvider('http://path.to.foo.api2'), resources: ['users2'] },
];

export default (type, resource, params) => {
  const dataProviderMapping = dataProviders.find(dp => dp.resources.includes(resource));
  return dataProviderMapping.dataProvider(type, resource, params);
};
Run Code Online (Sandbox Code Playgroud)


Rya*_*yan 5

如果您想知道如何拥有多个数据源以及多个 dataProvider 类型,即 Rest、GraphQL 等,v3 文档指出:

在react-admin v2中,数据提供者曾经是函数,而不是对象。React-admin v3 可以检测旧版数据提供程序并在其周围包装一个对象。因此,为react-admin v2开发的数据提供程序仍然适用于react-admin v3。

这意味着<Admin>组件上的 dataProvider 属性可以采用:

  • DataProvider 类型的对象
  • 提供(类型、资源、参数)返回包含数据的承诺的函数。

这意味着,如果您提供的 DataProvider 是一个函数,则必须创建一个适配器并手动调用提供程序上的函数。这是一个例子。

./dataProviders.js

import { gqlDataProvider, restGQLDataProvider, restProvider } from './buildDataProviders';

// The first assumption is that all resources are unique, thus we can use an object or a map instead of an array. Key = resource, value = DataProvider.
const dataProviders = new Map([
  ['users', restGQLDataProvider],
  ['users-local', restProvider],
  ['Invoice', gqlDataProvider],
  ['Debtor',  gqlDataProvider],
  ['Status',  gqlDataProvider]
]);

export default async (type, resource, params) => {
  // Get the DataProvider from the map.
  const dataProvider = await dataProviders.get(resource);

  // The DataProvider object is wrapped in a function so we can pass in the parameters to get the result.
  if (dataProvider instanceof Function) {
    return dataProvider(type, resource, params);
  }
};
Run Code Online (Sandbox Code Playgroud)

./buildDataProvider.js

import { gql } from 'apollo-boost';
import buildGraphQLProvider from 'ra-data-graphql-simple';
import { gqlClient, restClient } from './apolloClients';
import simpleRestProvider from 'ra-data-simple-rest';

const LOCAL_REST_ENDPOINT = 'http://localhost:3001/api';

export RestProvider = simpleRestProvider(LOCAL_REST_ENDPOINT);

export const gqlDataProvider = buildGraphQLProvider({
  client: gqlClient
});

// This is just an example of the getList provider, you'll have to write the rest.
export const restProvider = (type, resource, params) => {
  const providerMap = new Map([
    ['GET_LIST', async () => { 
      return await RestProvider.getList(resource, params);
    }]
   ])

export const restGQLDataProvider = (type, resource, params) => {
  const providerMap = new Map([
    ['GET_LIST', async () => {
      const query = gql`
        query ${resource} {
          ${resource} @rest(type: "${resource}", path: "/${resource}") {
              id
              name
              username
              email
              address
              phone
              website
              company
            }
          }
        `;
      
      const result = await restClient.query({ query });
          
      return { data: result.data[resource], total: result.data[resource].length };
    }]
  ])
}
Run Code Online (Sandbox Code Playgroud)

./apolloClients.js

import { ApolloClient, ApolloLink, InMemoryCache, HttpLink } from 'apollo-boost';
import { RestLink } from 'apollo-link-rest';
import auth from '../../auth';

const GRAPHQL_ENDPOINT = 'http://localhost:4000';
const REST_ENDPOINT = 'http://jsonplaceholder.typicode.com';
const httpLink = new HttpLink({ uri: GRAPHQL_ENDPOINT });
const authLink = new ApolloLink((operation, forward) => {
  operation.setContext({
    headers: {
      'x-api-key': auth.aws_appsync_apiKey
    }
  });

  return forward(operation);
});

export const restClient = new ApolloClient({
  link: new RestLink({ uri: REST_ENDPOINT }),
  cache: new InMemoryCache()
});

export const gqlClient = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache()
});
Run Code Online (Sandbox Code Playgroud)