apollographql / apollo-client

:rocket:  A fully-featured, production ready caching GraphQL client for every UI framework and GraphQL server.
https://apollographql.com/client
MIT License
19.31k stars 2.65k forks source link

Partial data returned on error after resetting cache #11938

Closed TuurDutoit closed 3 weeks ago

TuurDutoit commented 1 month ago

Issue Description

In our app, useQuery sometimes returns partial data after resetting the cache (client.resetStore()) and receiving an error.

We have a React Native app that uses Apollo for most data fetching. Our Apollo client is initialized like so:

const client = new ApolloClient<any>({
  link,
  cache,
  defaultOptions: {
    watchQuery: {
      fetchPolicy: 'cache-and-network',
    },
  },
})

Note that the default errorPolicy is none and the default returnPartialData is false.

We have a home screen that fetches some data with a useQuery hook. In our settings screen, it's possible to change your language and log out, among other things. Both these actions will cause the Apollo cache to be cleared (client.resetStore), to ensure we're not saving any data from other users or data in the wrong language. This in turn causes the home screen query to refetch automatically.

If you do so, and our GraphQL API returns an error with partial data while refetching the home screen query, useQuery suddenly returns the partial data. With our Apollo client config, useQuery should never return partial data.

Successful query:

const { data, error } = useQuery(...)
// data: full response
// error: undefined

Failed query:

const { data, error } = useQuery(...)
// data: undefined
// error: Error

After client.resetStore() and error from API on refetch:

const { data, error } = useQuery(...)
// data: partial data!
// error: Error

We use @apollo/client 3.7.7 currently, but I've tried on the latest (3.10.8), with the same result. The linked example is also using the latest version.

Link to Reproduction

https://codesandbox.io/p/devbox/peaceful-hopper-mtpd9x

Reproduction Steps

Click the "Reset cache" button a few times in quick succession. For me, it always happens after 3 clicks. I'm not sure why that's needed in this simple example - in our app, a single client.resetStore() will trigger the issue.

Expected outcome

Raw data is always undefined

Actual outcome

At some point, it becomes an object, with some of the requested data (notice how name is missing, breaking the list!)

Screen recording

https://github.com/apollographql/apollo-client/assets/4077287/4a255fac-4e8d-4b54-8380-b9a5c2a16861

@apollo/client version

3.7.7

jerelmiller commented 1 month ago

Hey @TuurDutoit 👋

We are in the middle of finalizing our 3.11 release and will try and take a look shortly after. Thanks for submitting the issue with a reproduction!

TuurDutoit commented 1 month ago

Another interesting find: if I add returnPartialData: true to the useQuery in the repro, the data stays undefined!

TuurDutoit commented 3 weeks ago

@jerelmiller I saw that 3.11 was released. Have you had a chance to look into this yet?

jerelmiller commented 3 weeks ago

Hey @TuurDutoit 👋

I just opened #11984 which should fix the issue. Turns out it didn't have much to do with resetStore itself, but rather multiple fetches where a result would return errors with the data property set. I was able to reproduce this with refetch by itself as well. I've tried the fix with your original reproduction and the issue is fixed.

Funny enough, I was able to reproduce this with 2 refetches as opposed to 3. I suspect it took 3 clicks on your reproduction because resetStore has some code to detect if its being called while a query is in flight (which kicked in on the 2nd click and avoided the request).

Could you try the following snapshot release to see if it fixes the issue in your actual app?

npm i @apollo/client@0.0.0-pr-11984-20240801210716

We'll either get this out with 3.11.3 or 3.11.4.

TuurDutoit commented 3 weeks ago

@jerelmiller That does seem to fix it in our app!

github-actions[bot] commented 3 weeks ago

Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo Client usage and allow us to serve you better.