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:
network-only
:
cache-and-network
:
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
Issue Labels
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!
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" />
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.
meet the same issue
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
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",
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",
Has anyone found a decent workaround for disabling the auto caching?
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() }}
@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.
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.
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
Any workaround for this? Seems like apollo client is not usable because of this issue!
@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.
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!
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 https://github.com/apollographql/apollo-client/issues/3452#issuecomment-389601457. 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 https://github.com/apollographql/apollo-client/pull/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!
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
?
@michaelknoch Can you try the recently released apollo-client
2.3.8 instead? Thanks!
the error still occurs, but only once in 5 app launches @hwillson
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' })
@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.
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.
All
no-cache
related items listed here should now be resolved. If anyone notices any additionalno-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 ano-cache
fetch policy indefaultOptions
is being ignored, is actually working as intended. React Apollo uses Apollo Client'swatchQuery
functionality, instead of itsquery
functionality. To setdefaultOptions
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
any progress on this? Im still running into the weird issue mentioned on August 9
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?
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.
@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
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.
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
@thanpolas https://github.com/apollographql/apollo-client/pull/4573 fixes that issue.
It appears https://github.com/apollographql/apollo-client/pull/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.
Since a lot of these issues have been fixed, let's open issues related to specific problems instead of one bulk one! Thank you!
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.
[process]
A. Whenever a new event occurs, cancel the previous abortController.
B. Reassign a new abortController.
[reason]
[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...
Most helpful comment
Using
fetchPolicy=no-cache
for me also results indata: {}
, even though the network response is present and visible.Specifically, I end up with:
when using
<Query fetchPolicy="no-cache" />
component .Here is a reproduction, showing how the data is missing:
https://codesandbox.io/s/4zmopq25o0
It also demonstrates different results when
defaultOptions
versus setting thefetchPolicy
component prop is used...Related: Using
defaultOptions
with afetchPolicy
forquery
does not seem to work - I get different behavior usingdefaultOptions: { query : { fetchPolicy: "no-cache" } }
and<Query fetchPolicy="no-cache" />
This seems to be supported according to tests and docs