Bart007
Bart007

Reputation: 111

react-admin graphql data provider: how to implement GET_MANY if GraphQL API only supports GET_ONE?

How to implement a GET_MANY data provider function in react-admin's ra-data-graphql package if the GraphQL API only supports the equivalent GET_ONE?

I understand how it can be done with REST by waiting on resolving all promises of the API call, but here the return from buildQuery is supposed to be an object with a key for the GraphQL query, and a key for a function parsing the response.

So how can this support multiple GraphQL queries, one for each ID we want to fetch, before we return the result from the data provider for GET_MANY?

Upvotes: 1

Views: 1536

Answers (2)

Bart007
Bart007

Reputation: 111

@kurtko sorry for late reply. Just checking this now. Found a workaround that does not require changes to GQL schema (since that is an external API I cannot change). You need to make changes to ra-data-graphql. Basically you need to allow for multiple GQL queries and then await until all promises resolve and return a combined result. By using either query or queries you can instruct ra-data-graphql to either run a single or multiple GQL queries. I modified index.js as follows:

// GRAPHQL QUERY
    if (operation === 'query') {
      if (!query.queries) {
        // single GraphQL query
        const apolloQuery = {
          ...query,
          fetchPolicy: 'network-only',
          ...getOptions(otherOptions.query, aorFetchType, resource),
        };

        return client
          .query(apolloQuery)
          .then((response) => parseResponse(response))
          .catch((error) => Promise.reject(error.message));
      } else {
        // multiple GraphQL queries
        const prs = query.variables.map((variables) => {
          const { queries, ...rest } = query;
          const apolloQuery = {
            ...rest,
            query: queries,
            variables,
            fetchPolicy: 'network-only',
            ...getOptions(otherOptions.query, aorFetchType, resource),
          };
          return client.query(apolloQuery);
        });
        return Promise.all(prs)
          .then((responses) => parseResponse(responses))
          .catch((error) => Promise.reject(error.message));
      }
    }

Upvotes: 1

kurtko
kurtko

Reputation: 2126

I had the same problem and solved with schema like this: (look {ids: [ID]} in UserFilter it's the important thing)

type Query {        
      Post(id: ID!): Post  
      allPosts(page: Int, perPage: Int, sortField: String, sortOrder: String, filter: PostFilter): [Post]
      _allPostsMeta(page: Int, perPage: Int, sortField: String, sortOrder: String, filter: PostFilter): ListMetadata
      User(id: ID!): User 
      allUsers(page: Int, perPage: Int, sortField: String, sortOrder: String, filter: UserFilter): [User]
      _allUsersMeta(page: Int, perPage: Int, sortField: String, sortOrder: String, filter: UserFilter): ListMetadata
}    

type User {
     id: ID!
     name: String!
     views: Int!
}

type Post {
     id: ID!
     title: String!
     views: Int!
     body: String
     user_id: ID!  
     User: User   
}        

input PostFilter {
      q: String
      id: ID
      title: String
      views: Int
      views_lt: Int
      views_lte: Int
      views_gt: Int
      views_gte: Int
      user_id: ID
}

input UserFilter {
    q: String
    ids: [ID]
    title: String
    views: Int
    views_lt: Int
    views_lte: Int
    views_gt: Int
    views_gte: Int
    user_id: ID
}

type ListMetadata {
    count: Int!
}

Upvotes: 0

Related Questions