Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mutations Nullify Intersecting Cache Objects #3468

Closed
zebulonj opened this issue May 17, 2018 · 9 comments
Closed

Mutations Nullify Intersecting Cache Objects #3468

zebulonj opened this issue May 17, 2018 · 9 comments
Assignees
Labels
🚧 in-triage Issue currently being triaged

Comments

@zebulonj
Copy link

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
apollo-boost@0.1.6
apollo-cache-inmemory@1.2.1
apollo-cache@1.1.8
apollo-client@2.3.1
apollo-link-dedup@1.0.9
apollo-link-error@1.0.9
apollo-link-http-common@0.2.4
apollo-link-http@1.5.4
apollo-link-state@0.4.1
apollo-link@1.2.2
apollo-utilities@1.0.12
react-apollo@2.1.4

@bessey
Copy link

bessey commented May 17, 2018

Just want to +1 that I have run into this issue on the same:
apollo-cache-inmemory@1.2.1
apollo-client@2.3.1
react-apollo@2.1.4
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!

@bessey
Copy link

bessey commented May 24, 2018

I wonder if this is related to the now merged but unreleased #3422 (details at #3419)

They certainly smell similar

@zebulonj
Copy link
Author

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

@hwillson hwillson self-assigned this Jun 14, 2018
@nbushak
Copy link

nbushak commented Jun 21, 2018

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.

@renanccastro
Copy link

+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.

@settings settings bot removed the refetch label Dec 12, 2018
@maxschmeling
Copy link

maxschmeling commented Jan 16, 2019

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.

@acro5piano
Copy link

acro5piano commented Apr 16, 2019

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.

@elimydlarz
Copy link

elimydlarz commented May 2, 2019

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?

@jbaxleyiii jbaxleyiii added the 🚧 in-triage Issue currently being triaged label Jul 9, 2019
@jbaxleyiii
Copy link
Contributor

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

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 16, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
🚧 in-triage Issue currently being triaged
Projects
None yet
Development

No branches or pull requests

9 participants