Apollo-client: Mutations Nullify Intersecting Cache Objects

Created on 17 May 2018  路  9Comments  路  Source: apollographql/apollo-client

Intended outcome:
Previously cached query should reflect changes in intersecting mutation result.

Actual outcome:
If a mutation returns a previously cached object, but it only returns a subset of the previously cached fields, queries watching the previously cached object subsequently return empty data.

How to reproduce the issue:

const query = gql`
  query SessionQuery {
    session {
      user {
        id
        email
        avatarUrl
      }
    }
  }
`;

const UserProfile = () => (
  <Query query={ query }>
    { ({ data = {} }) => {
      <div>
        <img src={ data.session.user.avatarUrl } />
      </div>
    }}
  </Query>
);

const mutation = gql`
  mutation UpdateAvatarMutation( $url: String! ) {
    updateAvatar( url: $url ) {
      user {
        id
        avatarUrl
      }
    }
  }
`;

const UpdateAvatar = () => (
  <Mutation mutation={ mutation }>
    { ( mutate ) => (
      <input type="text" placeholder="Your Gravatar url" onChange={ e => mutate({ variables: { url: e.target.value } }) } />
    )}
  </Mutation>
);

The user information in the SessionQuery will initially be cached and watched by the UserProfile component. When the UpdateAvatarMutation executes and returns, the query in the UserProfile component will receive empty data. Several others have also observed this behavior and all traced it to an imperfect overlap between the queried/cached fields and the fields returned on the mutation (in this example, email is missing from the User node on the mutation's returned results.

Version
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]

馃毀 in-triage

Most helpful comment

Looks like @hwillson has started grouping related issues under the refetch label -- just wanted to say thank you ahead of time, @hwillson. This class of issues has been responsible for the vast majority of apollo-implicated bugs in our production app over the past year -- it's so awesome that you're working on improving the behavior here.

All 9 comments

Just want to +1 that I have run into this issue on the same:
[email protected]
[email protected]
[email protected]
It is _very_ hard to reproduce, to the point that I have never intentionally reproduced it locally, but have seen multiple users hit it in different parts of our Apollo application, and even accidentally reproduced locally, though never when I've had my damn devtools open to trigger my debugger sadly!

I wonder if this is related to the now merged but unreleased https://github.com/apollographql/apollo-client/pull/3422 (details at https://github.com/apollographql/apollo-client/pull/3419)

They certainly smell similar

@bessey Could be, but I see a key difference in the fact that the issue I鈥檓 seeing occurs even when the query includes an explicit id on the relevant object.

Looks like @hwillson has started grouping related issues under the refetch label -- just wanted to say thank you ahead of time, @hwillson. This class of issues has been responsible for the vast majority of apollo-implicated bugs in our production app over the past year -- it's so awesome that you're working on improving the behavior here.

+1
It's really hard to reproduce on our app, but from time to time we get some errors about data being empty with the same mutation/query intersecting fields situation.

I'm running into this issue (currently on the 2.5.0-alpha.10 of apollo-client) but I think in a slightly different scenario. In my case, I have a mutation that returns two fields, where the second field is an object that is contained as a child of the first field. If I remove the first field from the result set, it starts working again.

So something like this:

mutation AddClip($id: ID!) {
  addClipToEpisode(id: $id) {
    episode {
      id
      clips {
        id
        name
      }
    }
    clip {
      id
      name
    }
  }
}

If I remove the episode field from the result set, everything works. With it, data is an empty object in the result and the episode query in my parent component gets cleared as well.

For now I've resorted to removing the episode field and then refetching the episode query after it's complete.

I had a similar problem in React Native and solved it.
I don't know that is related to this issue, but I'd like to share it.

My problem was that props.data.*** became undefined when I run two queries in different screens:

Screen 1:

export default graphql(gql`
  query GetUsers {
    users {
      id
      images {
        id
        url
      }
    }
  }
`)(props => <Text>{props.data.users[0].id}</Text>)

Screen 2:

export default graphql(gql`
  query GetUser {
    user(id: 1) {
      id
      images {
        # id      <-- I did not fetch id in Screen 2
        url
      }
    }
  }
`)(props => <Text>{props.data.user.id}</Text>)
  • Show Screen 1
  • GetUsers will be executed
  • Show Screen 2
  • GetUser will be executed
  • Go back to Screen 1
  • data.user will be undefined so Screen 1 will throw an Error

So I added id field to GetUser->user->images and fixed it.

Hope this helps.

I am experiencing the same symptoms. As others have said, the issue is difficult to reproduce. When it does crop up it is very consistent for some time - it happened twice and each time I spent an hour trying to figure out what I broke (nothing) before things magically worked again.

In my case, testing in an incognito window worked fine. On both occasions I was using my app simultaneously in a regular browser window (which was failing as per this issue) and an incognito window (which was working fine). Are other people experiencing this? Could it be that the cache (which I persist using AWS App Sync) can get into a particular state that makes this bug possible?

Thanks for reporting this. Would you be able to provide a small runnable reproduction that demonstrates this problem and create a new issue?

Was this page helpful?
0 / 5 - 0 ratings