Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

'cache-and-network' fetch policy on loading stage shows unrelated data (w/ testcase) #1342

Closed
lebedev opened this issue Nov 17, 2017 · 12 comments

Comments

@lebedev
Copy link

lebedev commented Nov 17, 2017

I made a simple React app with pagination with cache-and-network fetch policy. Not a lot of data, 3 pages total. Different pages use the same GraphQL query, but with different variables (offset-based pagination). The issue is that on loading stage it's impossible to determine whether the data in props is a cached version from current (query-variables) pair or is it from previous (query-variables) pair (same query, different variables).

Test case.
Here.

Intended outcome:
App starts. Props change over time:
{ loading: true, data: undefined, variables: varsForPage1 } ->
{ loading: false, data: dataForPage1, variables: varsForPage1 }
Switch to page 2. ->
{ loading: true, data: undefined, variables: varsForPage2 } ->
{ loading: false, data: dataForPage2, variables: varsForPage2 }
Switch to page 3. ->
{ loading: true, data: undefined, variables: varsForPage3 } ->
{ loading: false, data: dataForPage3, variables: varsForPage3 }
Switch back to page 2. ->
{ loading: true, data: dataForPage2, variables: varsForPage2 } ->
{ loading: false, data: dataForPage2_updated, variables: varsForPage2 }

Actual outcome:
{ loading: true, data: undefined, variables: varsForPage1 } ->
{ loading: false, data: dataForPage1, variables: varsForPage1 }
Switch to page 2. ->
{ loading: true, data: dataForPage1, variables: varsForPage2 } ->
{ loading: false, data: dataForPage2, variables: varsForPage2 }
Switch to page 3. ->
{ loading: true, data: dataForPage2, variables: varsForPage3 } ->
{ loading: false, data: dataForPage3, variables: varsForPage3 }
Switch back to page 2. ->
{ loading: true, data: dataForPage2, variables: varsForPage2 } ->
{ loading: false, data: dataForPage2_updated, variables: varsForPage2 }

How to reproduce the issue:
Here's the repo, forked from react-apollo-error-template.

Version

  • apollo-client@2.0.2
  • react-apollo@2.0.1
@yrypka
Copy link

yrypka commented Mar 13, 2018

I have encountered the same issue. It is reproducible with default fetch policy cache-first as well.

Executing a query with a new set of variables results in loading: true and a list of items for a previous set of variables until new data arrives.

Version

"apollo-client": "^2.2.2"
"react-apollo": "^2.0.4"

The same situation with:

"apollo-client": "2.2.5"
"react-apollo": "2.1.0-beta.3"

@jason-shen
Copy link

I have the same issue with login token did you guys manage to sort this out?

@yrypka
Copy link

yrypka commented Mar 20, 2018

@jason-shen No, unfortunately.

@jason-shen
Copy link

@yrypka if you on react-native, have a look at a package call react-native-restart which refresh the whole app clears all the cache on logout, that's what i am doing for now until some solution comes up, its kinda bad of this library, as this is just a simple task, just don't believe there isn't seem to be a way around it, i have try so many ways to solve this but no luck, i have wasted a week of trying to sort this out, in the end i kinda give up

@yrypka
Copy link

yrypka commented Mar 20, 2018

@jason-shen It looks like using data.networkStatus is a way out.

From docs:

data.loading

However, just because data.loading is true it does not mean that you won’t have data. For instance, if you already have data.todos, but you want to get the latest todos from your API data.loading might be true, but you will still have the todos from your previous request.

data.networkStatus

data.networkStatus is useful if you want to display a different loading indicator (or no indicator at all) depending on your network status as it provides a more detailed view into the state of a network request on your component than data.loading does.

  1. setVariables: If a query’s variables change and a network request was fired then the network status will be setVariables until the result of that query comes back. React users will see this when options.variables changes on their queries.

So it appears to be intended behavior and current issue is not a bug.

Taking said above into account something like so should be possible to do:

graphql('query', {
  options: {
    variables: { ... },
    notifyOnNetworkStatusChange: true,
  },
  props: ({
    data: { loading, networkStatus, feed = [], fetchMore },
  }) => ({
    loading,
    feed: networkStatus !== 2 ? feed : [],
    fetchMore: () =>
      fetchMore({
        variables: { ... },
        updateQuery: (prev, { fetchMoreResult }) => {
        },
      }),
  }),
})

@jason-shen
Copy link

@yrypka cheers for this, will give it another go, thanks once again

@jason-shen
Copy link

@yrypka this looks fancy for a simple logout clear the cache haha

@jason-shen
Copy link

@yrypka i had a good look, this would be ideal but, the token is going with the header tag, so that would be another problem to solve

@jason-shen
Copy link

because i have try the updateQuery, before, that still takes the old token, that doesn't access, only in the cache

@yrypka
Copy link

yrypka commented Mar 25, 2018

@jason-shen Maybe you are looking in the wrong direction. Check this link: https://www.apollographql.com/docs/react/recipes/authentication.html#login-logout

@jason-shen
Copy link

I have follow that but no go, it gives unauth when reserstore

@hwillson
Copy link
Member

It doesn't sound like there is still an issue here, so I'll close this for now. Happy to re-open if needed. Thanks!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants