如何在 React Admin 中共享一个 api 对不同资源名称的调用

How to share one api call to different resource names in React Admin

我正在使用 react-admin,我有以下资源:

所以我需要从这里添加一个 Images 和一个 videos 资源。像这样:

因此,正如您在上图中所见,ImagesVideos 应该 来自同一个端点,称为 Post .

现在,我在图片中向您展示的内容实际上不起作用。为什么?因为我没有 ImageVideos 端点。每次我点击它们时,它都会带我到 http://localhost:3000/dahboard/Imageshttp://localhost:3000/dahboard/Videos,这又不存在。我的 Posts 端点确实有我需要的内容,它有图像和视频。

我需要什么

我需要的是像我发布的图片那样显示的东西。我可以点击 ImagesVideos,无论端点是否直接转到 http://localhost:3000/dahboard/Post。但是我在react-admin文档中好像找不到相关的东西。

我目前拥有的

<Admin 
      layout={MyLayout} 
      theme={theme} 
      dataProvider={dataProvider}
    >
      <Resource name="Post"  {...posts} icon={ImageIcon} />
      <Resource name="Comment" {...comments} icon={ChatIcon} />
      <Resource name="User" {...users} icon={PeopleIcon} />
</Admin>

文件夹结构

|-- node_modules
|-- public
|-- src
  |---- comments
  |---- components
  |---- pages
  |---- posts
    |--- index.js
    |--- PostList.js
    |--- PostShow.js
  |---- users
    |--- index.js
    |--- UserList.js
    |--- UserShow.js
  |---- util
  |---- videos 
    |--- index.js
    |--- VideoList.js
    |--- VideoShow.js

编辑

这就是我配置数据提供程序的方式,为此我使用了 Hasura 的数据提供程序:

function DashboardPage(props) {
  const [dataProvider, setDataProvider] = useState(null);

  useEffect(() => {
    const buildDataProvider = async () => {

      const myClientWithAuth = new ApolloClient({
        uri: process.env.NEXT_PUBLIC_HASURA_GRAPHQL_ENDPOINT,
        cache: new InMemoryCache(),
        headers: {
          'x-hasura-admin-secret':
            process.env.NEXT_PUBLIC_HASURA_GRAPHQL_API_KEY,
        },
      });

      const dataProvider = await buildHasuraProvider({
        client: myClientWithAuth,
        getList: (resource, params) => {
          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),
          };
          const endpoint = resource === 'images' || resource === 'videos' 
            ? 'posts'
            : resource;

          const url = `${apiUrl}/${endpoint}?${stringify(query)}`;
          
          return httpClient(url).then(({ headers, json }) => ({
            data: json,
            total: parseInt(headers.get('content-range').split('/').pop(), 10),
          }));
        }
      })

      setDataProvider(() => dataProvider);
      
    };
    buildDataProvider();
  }, []);

  if (!dataProvider) return <p>Loading...</p>;

return (
    <Admin 
      layout={MyLayout} 
      theme={theme} 
      dataProvider={dataProvider}
    >
      <Resource name="Post" {...posts} icon={ImageIcon}  />
      <Resource name="Comment" {...comments} icon={ChatIcon} />
      <Resource name="User" {...users} icon={PeopleIcon} />
    </Admin>
  );

放置该逻辑的正确位置是 dataProvider。您可以将资源名称映射到不同的端点。类似于:

const dataProvider = {
    getList: (resource, params) => {
        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),
        };
        const endpoint = resource === 'images' || resources = 'videos'
           ? 'posts'
           : resource; 
        const url = `${apiUrl}/${endpoint}?${stringify(query)}`;

        return httpClient(url).then(({ headers, json }) => ({
            data: json,
            total: parseInt(headers.get('content-range').split('/').pop(), 10),
        }));
    },
   // ...
}