Apollo-client: UpdateQueries with inline fragments fails

Created on 17 Mar 2017  路  9Comments  路  Source: apollographql/apollo-client

I have a query that looks something like this:

query getGraph {
  nodes {
    ...NodeContent
  }
}
${nodeFragment}

where nodeFragment is:

fragment NodeContent on Node {
  id
  type
  x
  y
  ... on TriggerNode {
    properties {
      trigger
    }
  }
  ... on ReplyNode {
    properties {
      reply
      keep
    }
  }
}

This runs fine, and I get back the desired result.

I then want to perform a mutation that adds a node, and therefore runs updateQueries. So I wrote a query like this:

mutation createNode ($type:String!, $x:Int!, $y:Int!, $properties:PropertiesInput!) {
  createNode(type:$type, x:$x, y:$y, properties:$properties) {
    ...NodeContent
  }
}
${nodeFragment}

And called it like this:

const withCreateNodeMutation = graphql(createNodeMutation, {
  props: ({ mutate }) => ({
    createNode: variables => mutate({
      variables,
      updateQueries: {
        getGraph: () => { console.log('hello world'); },
      },
    }),
  }),
});

Intended outcome:

I expected the client to at least run the updateQueries function and print hello world in the console.

Actual outcome:

Nothing happens!

Interestingly, I am getting back the correct, complete result in the APOLLO_MUTATION_RESULT action (with the correct __typenames on the fragments and everything). The updateQueries function is just not called.

This also makes optimistic UI impossible.

Could be related to #1363, #1379?

Would appreciate any thoughts or workarounds - perhaps the new imperative API? Thanks!

Most helpful comment

@Mike-Dax I upgraded to [email protected] (and therefore [email protected]), and also passed my schema into fragmentMatcher on the apollo client options but it seems to have made no difference.

updateQueries is still never called (no console.log). I traced this through Chrome's debugger: it seems that context.hasMissingField is being set to true during diffQueryAgainstStore, causing it to short circuit out of updateQueries. I'm afraid I don't know enough about that code to be able to help on that front further!

If I use update, I can update the store fine (looking at the next state via the APOLLO_MUTATION_RESULT reducer shows the correct updated store), but it won't update the props passed down into my component that uses the updated query.

The only reliable option still seems to be refetchQueries.

All 9 comments

@benhjames I think this is related to the issues you mentioned and also to #1337. Because of its heuristic fragment matching, Apollo Client doesn't know for sure whether the response is complete and seems to think that it's in fact incomplete. This in turn leads to not running the updateQueries function. We're working on a non-heuristic fragment matcher that will not have this issue, and I'm hoping to finish and release it by next week.

I don't think there are currently any workarounds, other than downgrading to rc.0.

@helfer, no worries - can make do with refetchQueries for now. Thanks for the speedy response and glad to hear it's being looked at!

@Mike-Dax I upgraded to [email protected] (and therefore [email protected]), and also passed my schema into fragmentMatcher on the apollo client options but it seems to have made no difference.

updateQueries is still never called (no console.log). I traced this through Chrome's debugger: it seems that context.hasMissingField is being set to true during diffQueryAgainstStore, causing it to short circuit out of updateQueries. I'm afraid I don't know enough about that code to be able to help on that front further!

If I use update, I can update the store fine (looking at the next state via the APOLLO_MUTATION_RESULT reducer shows the correct updated store), but it won't update the props passed down into my component that uses the updated query.

The only reliable option still seems to be refetchQueries.

@benhjames could you provide a replication of the issue using https://github.com/apollographql/react-apollo-error-template? I would take a look at it.

@msimulcik sure, bit of a hectic week so hope you don't mind waiting a little bit - cheers!

@msimulcik Sorry for the delay: I've produced a minimal example repo here: https://github.com/benhjames/apollo-fragment-issue

The most important thing about this is that if you remove the ... on ReplyNode and ... on TriggerNode fragments from the query/mutation, it works just fine. As soon as you add in the fragments, the client stops calling updateQueries etc.

Interestingly, somewhere between [email protected] and [email protected], refetchQueries also stopped working.

Do let me know if there's anything else you need info-wise. Cheers :)

@helfer I think I found the culprit for this: https://github.com/apollographql/apollo-client/blob/master/src/data/fragmentMatcher.ts#L146

Currently (and as noted in the comment there), the HeuristicFragmentMatcher will positively match a TriggerNode fragment with a ReplyNode fragment despite referencing different (interface) types. Ultimately that results in hasMissingField being set to true, and the updateQueries stuff not firing.

If I change the bottom return true to return false, it works as expected i.e. doesn't match a fragment on TriggerNode as a fragment on ReplyNode. But again as the comment specifies there, I'm sure it's more complicated than that.

Was wondering what your thoughts were on this. :)

I must have done something incorrect when I previously tried using IntrospectionFragmentMatcher - I've now followed the steps outlined in #1555 and it works just fine!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

helfer picture helfer  路  3Comments

joergbaier picture joergbaier  路  3Comments

canercandan picture canercandan  路  3Comments

stubailo picture stubailo  路  3Comments

kriswep picture kriswep  路  3Comments