GraphQL: How to implement a GraphQLList of GraphQL

2019-07-22 15:20发布

问题:

I have an issue with GraphQL (Specifically, implementing GraphQLList)

I have a query getItemByName that correctly returns an Item, with Type itemType. But I haven't been able to implement a getItemList (Or a proper example btw). I know that it's supposed to have a type that implements GraphQLList.

But am i doing it right? What's the data format that resolve should recieve? (Or that getItems() should return). An array of objects? Should those objects be implementing "itemType" definition? Should an interface be implemented?

export const itemType = new GraphQLObjectType({
  name: 'Item',
  fields: {
    name: {
      type: GraphQLString,
      description: 'Item Name',
    },
  },
});

const itemListType = new GraphQLObjectType({
  name: 'ItemsList',
  fields: {
    items: {
      type: new GraphQLList(itemType),
      description: 'List of items',
    },
  },
});

{...}

const schema = new GraphQLSchema({
    query: new GraphQLObjectType({
        name: 'Query',
        fields: {
           itemList: {
               type: itemListType,
               resolve: () => getItems(),
           }
        }
    })
})

As it is now, the query:

itemList {
  items {
    name
  }
}

its returning:

{
  "data": {
    "itemList": {
      "items": null
    }
  }
}

Any help is really really welcome! :D

Regards!

回答1:

I'll first explain the root cause of your problem. Then I'll discuss how GraphQLList is generally used.

In your schema query, itemList field is of type itemListType. Now this itemListType has a field items. Therefore, the query's itemList field must be resolved to an object which has an items field. But the getItems() function returns an array or a promised array and does not have field items. That's why you're getting "items": null in the query response.

Now about the confusion around GraphQLList: if it's just a list, there's actually no need to define a separate GraphQL type for that. In your query, you include a field with type GraphQLList of item type:

const schema = new GraphQLSchema({
    query: new GraphQLObjectType({
        name: 'Query',
        fields: {
           itemList: {
               type: new GraphQLList(itemType),
               resolve: () => getItems(),
           }
        }
    })
});

If your list is not that simple, for instance, itemList actually has two fields(oldItems, newItems - both are lists), you should define a separate type. Remember to modify the resolve function accordingly:

itemList: {
  type: itemListType,
  resolve: () => {
    // get new items
    // get old items
    return {
      newItems, 
      oldItems
    };
  },
},

(By the way, your code has some syntax errors like itemsList, itemList, itemsListType, itemListType. I have edited your question. The changes will appear after my edit is approved.)



回答2:

getItems() should return an array of itemType objects (or a promise for one). What those itemTypes look like is up to you. They'll simply be passed to the resolve function of the fields that you asked for in itemType.



回答3:

Fixed the issue. It was not a problem with the structure of data that I was returning, it was the way i was defining a the query.

export const coworkList = {
  name: 'coworkList',
  description: 'Returns a list (up until 10) of coworks',
  type:  new GraphQLList(coworkType),
  resolve: () => getCoworks(),
};

The coworkListquery definition is that is now being passed into the schema. Works great! const schema = new GraphQL

Schema({
  query: new GraphQLObjectType({
    name: 'Query',
    fields: () => ({
      coworkList,
      coworkByName,
      coworkById,
    }),
  }),
});