Search code examples
graphqlrelayjsgraphql-jsapolloreact-apollo

Apollo GraphQL server: In resolvers, get variables from several levels higher


Say in my resolvers I have the following:

Query: {
  author: (root, args) => API.getAuthor(args.authorId),
},
Author: {
  book: (author, args) => API.getBook(author.id, args.bookId),
},
Book: {
  // Here, I can't get the author ID
  chapter: (book, args) => API.getChapter(authorId???, book.id, args.chapterId),
}

My problem is pretty clear from the above example, how can I access variables from several levels higher? I'd like to be able to make a request like the following:

author(authorId: 1) {
  id
  book(bookId: 31) {
    id
    chapter(chapterId: 3) {
      content
    }
  }
}

And my connector to get a specific chapter also need the author's ID.


Solution

  • You can't access variables from levels higher in GraphQL.

    This is intended : because the Book entity can also be included in others objects. Right now, you have author { book { chapter } }, but you could also have library { book { chapter } }, where the author field would not present in the query, thus making the author.id variable inaccessible.

    Each object is responsible for fetching his fields with his own data, which makes the whole thing composable.

    What you could do, though, is extending the response of the API.getBooks function, to add the author_id field to the returned object. This way, you will be able to access it inside your Book entity : book.authorId.

    function myGetBook(authorId, bookId) {
      return API.getBook(authorId, bookId)
        .then(book => {
          return Object.assign(
            {},
            theBook,
            { authorId }
          );
        });
    }
    

    And then:

    Author: {
      book: (author, args) => myGetBook(author.id, args.bookId),
    },
    Book: {
      chapter: (book, args) => API.getChapter(book.authorId, book.id, args.chapterId),
    }