useQuery with fetchPolicy: 'network-only', returns stale cached results.
See original GitHub issueThis is very similar to (or maybe the same as) #7048. I’m using useQuery
with fetchPolicy: 'network-only'
. In certain cases, it does not make a network request, and returns not just cached results, but stale cached results.
In my app I have asynchronous processes on backend, that take forever. After I do a mutation, I do an optimistic update with cache.modify
in update
function, and then startPolling
on a query to continuously check if the operation is complete. This worked very well when I used Apollo V2. Not after the upgrade to V3.
Here’s my custom hook that manages mutations and status checks:
const useItem = (someName) => {
let variableToSync;
const {data, loading, startPolling, stopPolling} = useQuery(
GET_ITEMS,
{
variables: {name: someName},
fetchPolicy: 'network-only',
pollInterval,
}
);
console.log('1 data', data?.apps?.apps[0]?.items);
console.log(
'1 cache',
window.__APOLLO_CLIENT__.cache.data.data['SomeID']
.items
);
const [addItem, {loading: adding}] = useMutation(
ADD_ITEM,
{
variables: {
someName: someName,
},
update: (cache, {data: res}) => {
if (!res.addItem?.ok || res.addItem?.error) {
return;
}
console.log(
'cache before modify',
window.__APOLLO_CLIENT__.cache.data.data['SomeID']
.items
);
cache.modify({
id: 'SomeID',
fields: {
items(existingRefs = []) {
return [
...existingRefs,
{
...variableToSync,
status: res.addItem.refresh ? 'started' : '',
__typename: 'Item',
},
];
},
},
});
if (res.addItem?.refresh) {
console.log('startPolling');
startPolling(pollInterval);
}
console.log(
'cache after modify',
window.__APOLLO_CLIENT__.cache.data.data['SomeID']
.items
);
},
}
);
console.log('2 data', adding, data?.apps?.apps[0]?.items);
if (
!adding &&
data?.apps?.apps[0]?.items?.every(
({status}) => status !== 'started' && status !== 'queued'
)
) {
console.log('stopPolling');
stopPolling();
}
return {
add: (variable) => {
variableToSync = variable;
return addItem({variables: variable});
},
adding,
items: (data?.apps?.apps[0]?.items || [])
.map((e) => ({
...e,
loading: e.status === 'started' || e.status === 'queued',
}))
.sort(sortBy('name')),
loading,
};
};
Intended outcome:
- Execute the query initially when loading the module
- User interaction prompts the mutation, which modifies the cache
startPolling
…- Hook start executing from the beginning, so the
console.log
’s after the query should both print stuff that query pulled from backend.
Actual outcome:
- There is actually no network request coming from the query. Instead I see two things in
console.log
:
1 data (3) [{…}, {…}, {…}] 1 cache (4) [{…}, {…}, {…}, {…}]
So the cache actually did update correctly after cache.modify
, but the data
returned by useQuery
returns some stale cache.
If I remove fetchPolicy: 'network-only'
, I get the correct cached result - which almost works for me, except if the above example gets extended to also do removeItem
, and then a user starts to add and remove things quickly, things start getting out of sync and weird stuff happens. Again - this exact code (minus the API adjustments for V3) worked perfectly on V2.
How to reproduce the issue:
Above
Versions System: OS: macOS 10.15.6 Binaries: Node: 12.13.1 - ~/.nvm/versions/node/v12.13.1/bin/node Yarn: 1.22.5 - /usr/local/bin/yarn npm: 6.12.1 - ~/.nvm/versions/node/v12.13.1/bin/npm Browsers: Chrome: 85.0.4183.121 npmPackages: @apollo/client: ^3.2.0 => 3.2.0 apollo-link-logger: git://github.com/dmt0/apollo-link-logger.git#support-apollo-v3 => 0.0.0-development apollo-upload-client: ^14.1.2 => 14.1.2 npmGlobalPackages: apollo-link-logger: 0.0.0-development
Issue Analytics
- State:
- Created 3 years ago
- Reactions:3
- Comments:7 (1 by maintainers)
Top GitHub Comments
@benjamn @dmt0 I think that we face almost the same issue with the stale data in cache when we make a Query with fetchPolicy=‘network-only’. In my example : https://github.com/apollographql/apollo-client/issues/7048 I see a network request made to the server however the data returned by the GraphQL server is not rendered by AC3 and instead Apollo Client cache pulls data from the cache and ignores backend returned data. As if Apollo Client v3 does something to prevent cache overwriting because normally when you specify fetchPolicy=‘network-only’ AC3 should then update the cache with backend data and does this automatically by matching the ID coming from the server and the ID of the object to be modified in cache. I think that maybe there could be another step to do in order to update the existing data in cache … This stuff works well with Apollo Client 2 (with returning ID) and now it seems that it is broken. I’m blocked right now 😕
+1