l2silver
l2silver

Reputation: 3439

How does relay or Apollo-react solve mutations that involve multiple relationships

Suppose I have a react application with these features on a single page: New books, Books by author xyz, Create new book

Now suppose I create a new book by author xyz. The page is updated in two places, there is one more new book, and there is one more book by author xyz.

How do apollo-react and relay differ in their approach to solving this issue? How do they solve this issue? Most of the examples I have seen only show rudimentary mutations

Upvotes: 3

Views: 306

Answers (1)

stubailo
stubailo

Reputation: 6147

Here's how to solve this in Apollo.

Let's say we're working with the following query for this part of the UI:

query AllBooks {
  newBooks {
    title
    author { name }
  }
  author(id: "stubailo") {
    id
    books {
      title
    }
  }
}

Of course in reality you might have some pagination, variables, etc. But for this example I'll just use something simple.

Now, let's write a mutation to create that new book, it might look like:

mutation CreateBook($book: BookInput!) {
  createBook(book: $book) {
    title
    author { name }
  }
}

Now, we have two main options in Apollo to handle this.

First option is to simply refetch the entire query:

client.mutate(CreateBookMutation, {
  variables: { book: newBook },
  refetchQueries: [ { query: AllBooksQuery } ],
})

This is simple and effective, but might not be efficient if for some reason that query result is super expensive to calculate.

The second option is to incorporate the result by updating the entire query result. You can use updateQueries, but the newest way recently introduced is to use the update callback on the mutation with the new imperative write API:

client.mutate(CreateBookMutation, {
  variables: { book: newBook },
  update: (proxy, mutationResult) => {
    // Get data we want to update, in the shape of the query
    const data = proxy.readQuery({ query: AllBooksQuery });

    // It's fine to mutate here since this is a copy of the data
    data.newBooks.push(mutationResult.createBook);
    data.author.books.push(mutationResult.createBook);

    // Write the query back to the store with the new items
    proxy.writeQuery({ query: AllBooksQuery, data });
  },
})

As you can see, with GraphQL it's not much easier than in other data loading solutions to keep the UI updated. The API doesn't give you much information about where the new data should go, so you have to tell Apollo what to do with it.

Notably, this is only the case for adding and deleting items - updating existing items works automatically.

Upvotes: 2

Related Questions