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

FetchPolicy seems to be moderately broken - summary #3452

Closed
8 tasks done
OllieJennings opened this issue May 14, 2018 · 34 comments
Closed
8 tasks done

FetchPolicy seems to be moderately broken - summary #3452

OllieJennings opened this issue May 14, 2018 · 34 comments
Assignees
Labels
🚧 in-triage Issue currently being triaged

Comments

@OllieJennings
Copy link

OllieJennings commented May 14, 2018

Like the title states, fetchPolicy in apollo-client seems to be completely moderately broken.

I thought it would be a good idea to round up all of the issues in a central place:

no-cache:

cache-and-network:

cache-only:

network-only:

Misc:

Issues related in React-Apollo repo:

network-only:

  • 556 : network-only returns cached value
  • 1895 : Fix network-only

cache-and-network:

  • 1342 : cache-and-network fetch policy on loading stage shows unrelated data
  • 1217 : Set network status to 3 with cache-and-network fetch policy

Personally l am experiencing all of the issues above in the latest version of apollo-client. It would be good to get these properly addressed as they are a pretty important part of apollo.

If anyone else has any more issues (closed or open) that can be linked into this, just comment below with it.

@evans and @jbaxleyiii Can we get this put as quite a high priority on the apollo-client Roadmap, if help is need, l can also look into these on the weekend

Version

  • apollo-client@2.3.1

Issue Labels

  • has-reproduction
  • blocking
  • bugs
@ghost ghost added has-reproduction labels May 14, 2018
@OllieJennings OllieJennings changed the title FetchPolicy seems to be completely broken - summary FetchPolicy seems to be moderately broken - summary May 14, 2018
@ghost ghost added blocking labels May 14, 2018
@hwillson
Copy link
Member

Thanks for putting this list together @OllieJennings! I've been working through all outstanding apollo-client issues, and will be getting to these shortly.

if help is need, l can also look into these on the weekend

Help is 💯% always welcome! If you're able to chip in by reviewing these issues and adding your comments, helping with reproductions, or better yet, working on PR's, that would be awesome!

@kristiehowboutdat
Copy link

kristiehowboutdat commented May 16, 2018

Using fetchPolicy=no-cache for me also results in data: {}, even though the network response is present and visible.

Specifically, I end up with:

loading: false,
error: undefined,
data: {},
...

when using <Query fetchPolicy="no-cache" /> component .

   // package.json
    "apollo-cache-inmemory": "1.2.1",
    "apollo-client": "2.3.1",
    "apollo-codegen": "0.19.1",
    "apollo-link": "1.2.2",
    "apollo-link-error": "1.0.9",
    "apollo-link-http": "1.5.4",
    "react-apollo": "2.1.4"

Here is a reproduction, showing how the data is missing:
https://codesandbox.io/s/4zmopq25o0

It also demonstrates different results when defaultOptions versus setting the fetchPolicy component prop is used...

Related: Using defaultOptions with a fetchPolicy for query does not seem to work - I get different behavior using defaultOptions: { query : { fetchPolicy: "no-cache" } } and <Query fetchPolicy="no-cache" />

This seems to be supported according to tests and docs

@kolpav
Copy link

kolpav commented May 22, 2018

I am not sure about this one it is just my quick observation but it seems that when using withApollo calling query with no-cache does not work at all it always updates the cache.

@wuzhuzhu
Copy link

meet the same issue

@raja
Copy link

raja commented Jun 14, 2018

I also had an issue with apollo-client being used in conjunction with apollo-link-state.

If I do not explicitly specify a 'no-cache' fetchPolicy on the for local state, I would get stale data on page change despite proper updates on the component before page change.

@michaelknoch
Copy link
Contributor

fetchPolicy: "no-cache" still seems to be broken

    "apollo-cache-inmemory": "1.2.5",
    "apollo-client": "2.3.5",
    "apollo-link-batch-http": "1.2.2",
    "apollo-link-error": "1.0.9",
    "apollo-link-http": "1.5.4",
    "react-apollo": "2.1.8",

@cristianPerez
Copy link

same here::

    "apollo-boost": "^0.1.1",
    "apollo-cache-inmemory": "^1.1.9",
    "apollo-client": "^2.3.5",
    "apollo-link-context": "^1.0.7",
    "apollo-link-http": "^1.5.1",

@james89
Copy link

james89 commented Jul 9, 2018

Has anyone found a decent workaround for disabling the auto caching?

@kristiehowboutdat
Copy link

We added a resolver that is a "cache buster" so that we send unique queries every time since the arguments are different given a unique id (using the uuid package). This only works if you can control the schema though.

query Document($documentId: String!, $uniqueId: String) {
   # Original query
  document(ID: $documentId) { ... }
  # This resolver just returns true and is used so that our query always has a unique arg
  cacheBuster(uniqueID: $uniqueId)
}
import uuid from 'uuid';
...
<Query query={documentQuery} variables={{ documentId: "1234", uniqueId: uuid.v4() }}

@jync
Copy link

jync commented Jul 10, 2018

@kristiehowboutdat wouldn't this also fill up your cache unnecessarily? Given the cache isn't a proper cache (with an LRU) this will cause your app's memory demand to increase.

@kristiehowboutdat
Copy link

kristiehowboutdat commented Jul 10, 2018

Yeah @jync, there are a couple of downsides, including that. It's a workaround, not a solution 😞 For our app we cannot have cached values, and using "no-cache" was not giving us the values from the server and causing lots of stale data to be displayed - this at least solved that. Curious how others have been working around this.

Would welcome suggestions on how to avoid filling the cache at all or clearing it. Last time I looked at the docs (1-2 months ago), I didn't find a good way to programmatically clear the cache.

@rajjejosefsson
Copy link

When I don't set the defaultOptions for ApolloClient, it uses the 'cache-first' as expected, but when I set it explicit with the defaultOptions it seems to use 'network-only' even If I have it set to 'cache-first'

example can be found here https://codesandbox.io/s/jjn4pnnz7v

@ngbinh
Copy link

ngbinh commented Jul 19, 2018

Any workaround for this? Seems like apollo client is not usable because of this issue!

@fbartho
Copy link

fbartho commented Jul 24, 2018

Related Issue: apollographql/apollo-link-state#272

@klis87
Copy link

klis87 commented Jul 25, 2018

@fbartho In a project in which I dont use apollo-link-state I have the same issues. The most important for me is that I have 1 view with many filters and pagination and caching is pointless there, but with cache-policy: 'no-cache' no data is rendered, despite the fact that in browser devtools I can see that response has data in it.

@hwillson hwillson removed the blocking label Jul 27, 2018
@hwillson hwillson self-assigned this Aug 2, 2018
@hwillson
Copy link
Member

hwillson commented Aug 2, 2018

Hi all - I'll be tackling this issue in chunks, since there is a lot covered here. First up is dealing with any outstanding no-cache issues. I've created a new temporary label to identify outstanding no-cache related issues; if anyone knows of issues I've missed with the label, please let me know. Thanks!

@hwillson hwillson removed the no-cache label Aug 3, 2018
@michaelknoch
Copy link
Contributor

Thanks @hwillson for your fix.

I tested the 2.4.0-alpha.14 release of apollo-client in my project. The issue still seems to occur when trying to load data with fetchPolicy "no-cache", but only sometimes.

I tried to debug my example and it looks like the query can resolve the data, but immediately removes it again.

1. fetch data --> { data: undefined, loading: true }
2. data was resolved successfully --> { data: [....], loading: false }
3. data was removed --> { data: undefined, loading: false, error: undefiend }

Anyone else experiencing this on 2.4.0-alpha.14?

@hwillson
Copy link
Member

hwillson commented Aug 9, 2018

@michaelknoch Can you try the recently released apollo-client 2.3.8 instead? Thanks!

@michaelknoch
Copy link
Contributor

the error still occurs, but only once in 5 app launches @hwillson

@jpgarcia
Copy link

I'm facing the same random issue as @michaelknoch. Not sure, but I found that if I delay the response from the server it will never return undefined but the actual data.

To test I'm using bluebird on the server with something like...

require('bluebird').delay(1000, { foo: 'bar' })

@senorgeno
Copy link

senorgeno commented Aug 22, 2018

@michaelknoch @hwillson i am getting the same issue as well. I am using 2.4.0. Occasionally it will work as expected, when it doesn't I can see the query keeps running periodically. The second and every query after that is returning an empty object.

@marvinkome
Copy link

I'm having an issue with the optimistic response. When fetch-policy="cache-first" optimistic response works flawless. But when its cache-and-network it doesn't work most time, and sometimes it just works.

@SergeyVolynkin
Copy link

SergeyVolynkin commented Oct 5, 2018

All no-cache related items listed here should now be resolved. If anyone notices any additional no-cache issues, please let me know.

@kristiehowboutdat Thanks very much for you repro in #3452 (comment). It really helped narrow down the issue. Just so you know, your reproduction is actually demonstrating 2 separate issues. The first problem is the fact that passing a no-cache fetch policy directly into your <Query /> component is broken (which is now fixed by #3777 and will be released soon). The second problem where you mentioned setting a no-cache fetch policy in defaultOptions is being ignored, is actually working as intended. React Apollo uses Apollo Client's watchQuery functionality, instead of its query functionality. To set defaultOptions properly when using React Apollo, you need to use something like:

const client = new ApolloClient({
  ...
  defaultOptions: {
    watchQuery: {
      fetchPolicy: "no-cache"
    }
  }
});

Now of course we don't have this documented anywhere, because we like to keep developers guessing ... 🤦‍♂️.

I'll make sure this gets added to the docs - thanks!

Using this approach:

const client = new ApolloClient({
  uri: 'https://graphql-pokemon.now.sh/',

  // Disable caching
  defaultOptions: {
    watchQuery: {
      fetchPolicy: 'no-cache'
    }
  }
})

causes Console warning:

ApolloBoost was initialized with unsupported options: defaultOptions

@michaelknoch
Copy link
Contributor

any progress on this? Im still running into the weird issue mentioned on August 9

@joelgetaction
Copy link

Hey @hwillson I am seeing the same issue as @SergeyVolynkin - your suggested fix does not work when importing ApolloClient from apollo-boost - it causes a warning: ApolloBoost was initialized with unsupported options: defaultOptions.

This is really frustrating ... if Apollo caching doesn't work, it really reduces the performance of Query components since the whole argument that it's OK to use them declaratively is that "it will load cached data first". If it's always going to fail in the cache and just load the network response, then Query components are a lot less performant than just doing the query ourselves in componentDidMount and caching ourselves, but then we have to do a bunch of state management ourselves ...

Does caching work if I setup the ApolloClient myself, i.e. do not use apollo boost?

@thanpolas
Copy link

We use apollo-client 2.4.1 and experienced issues with no-cache:

From what we could gather, for no apparent reason, once every few times (less than 10 in our case) the Query component will trigger twice when fetchPolicy is set to no-cache. The first invocation will have the data, the second invocation will not.

We have replaced all our "no-cache" policies with "network-only" and will continue monitoring.

@settings settings bot removed blocking labels Dec 12, 2018
@rstrand
Copy link

rstrand commented Jan 16, 2019

@rajjejosefsson

When I don't set the defaultOptions for ApolloClient, it uses the 'cache-first' as expected, but when I set it explicit with the defaultOptions it seems to use 'network-only' even If I have it set to 'cache-first'

example can be found here https://codesandbox.io/s/jjn4pnnz7v

The react Query component uses watchQuery and not query. If you change the defaultOption of watchQuery to 'cache-first' then it works as expected.

I have fixed your example here https://codesandbox.io/s/68q5p5vow

@andreasdjs
Copy link

Yeah @jync, there are a couple of downsides, including that. It's a workaround, not a solution 😞 For our app we cannot have cached values, and using "no-cache" was not giving us the values from the server and causing lots of stale data to be displayed - this at least solved that. Curious how others have been working around this.

Would welcome suggestions on how to avoid filling the cache at all or clearing it. Last time I looked at the docs (1-2 months ago), I didn't find a good way to programmatically clear the cache.

I am using withApollo() and no-cache does not work for me either.

I ended up with a workaround using client.resetStore() directly after a mutation to empty the cache.

@michaelknoch
Copy link
Contributor

michaelknoch commented Jan 29, 2019

I was able to reproduce it within the original apollo codesandbox example by setting the fetchPolicy to "no-cache" https://codesandbox.io/s/k9y4v0wlov.

Due to some experiments I think this issue is a bug in react-apollo. The watchquery itself seems to work as expected, but maybe im wrong

@bradleyayers
Copy link
Contributor

@thanpolas #4573 fixes that issue.

benjamn pushed a commit to bradleyayers/apollo-client that referenced this issue Apr 8, 2019
benjamn pushed a commit that referenced this issue Apr 8, 2019
Avoid updating (and later invalidating) cache watches when fetchPolicy is no-cache.

Part of #3452.
@fracmak
Copy link
Contributor

fracmak commented Apr 9, 2019

It appears #4352 introduced a new bug related to fetch-policy: 'no-cache'. The original QueryManager code would would call this.dataStore.getCache().read() inside getCurrentQueryResult(), which would throw an exception and return { data: undefined, partial: true };, which would get detected here: https://github.com/danilobuerger/apollo-client/blob/b200a054d955daaf199aa052ee4d1d7ce8badbc7/packages/apollo-client/src/core/ObservableQuery.ts#L216-L218 as loading: true. After the change, getCurrentQueryResult() now return { data: undefined, partial: false }; and so a call to getCurrentResult() would return { loading: false, data: undefined, networkStatus: 7 }; Indicating that all data had been returned successfully, even though queryLoading was actually true and a query was actually being rendered.

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

Since a lot of these issues have been fixed, let's open issues related to specific problems instead of one bulk one! Thank you!

@bedcoding
Copy link

I have a similar problem.
I made a search cancellation like this.
However, there is a problem that 'words that have already been canceled' are not recalled.

EX)
If "apple" is cancelled, it searches up to "appl",
but "apple" does not re call api.

  • I don't speak English, so I use Google Translate.

[process]
A. Whenever a new event occurs, cancel the previous abortController.
B. Reassign a new abortController.

[reason]

  • abortController.abort() only worked the first time.
  • because abortController only looks at the 'first called API'.
  • So, every time I call the API, I allocate abortController again.

스크린샷 2020-10-16 오후 3 29 10

[logic1]

   const [_controller, set_controller] = useState(new AbortController());   // state

[logic2]

      const { GET_MY_NAME } = query;
      const [getMyData] = useLazyQuery(GET_MY_NAME, {
        fetchPolicy: "no-cache",
        variables: { myword: myword },
        context: {
          fetchOptions: {
            signal: _controller.signal
          }
        },
         
        onCompleted: (data) => {
            // get data!!    ex) dispatch(nameActions.setName(data.name));
        }
     });

[logic3]

  let timer = null;

  const onChange = (e) => {
     // 1. kill old API
      _controller.abort();  

      // 2. Initialize setTimeout when new input comes in
      clearTimeout(timer);  
      
     // 3. state update, API start
      timer = setTimeout(async (_) => {
          await set_controller(new AbortController());  
          await getMyData();
      }, 500);
  }

[logic4]

          <input
            onChange={onChange}
          />

[Method currently being considered]

I am thinking of a method of separating components only in the search box and fetching components whenever they are called...

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