Intended outcome:
I want to show my users that the app is loading fresh data in the background when they get a render from the cache. (i.e. fetchPolicy is set to cache-and-network) In our app, this mostly happens when users navigate back to a page they've been on previously and we render the data from the cache first, while using cache-and-network to load fresh data from the server.
Actual outcome:
I can't do that because networkStatus does not expose that information.
Idea:
Rather than networkStatus 3 being specific to this.props.data.refetch(), why not also set the networkStatus to 3 when the data is refetched by the cache-and-network fetch policy? The data is being _refetched_ (even if not by calling refetch()) so it makes sense for the networkStatus to reflect that reality.
This issue has been automatically labled because it has not had recent activity. If you have not received a response from anyone, please mention the repository maintainer (most likely @jbaxleyiii). It will be closed if no further activity occurs. Thank you for your contributions to React Apollo!
Hah @stale take that, now I can label it myself! 馃枙馃槅 (thanks @jbaxleyiii)
This might've been fixed with the Apollo Client 2.0 rewrite which would be awesome, but I can't confirm that as we haven't had time to upgrade yet.
Using Apollo Client 2.0, I can confirm that networkStatus is still 1 while using cache-and-network fetch policy.
This issue has been automatically labled because it has not had recent activity. If you have not received a response from anyone, please mention the repository maintainer (most likely @jbaxleyiii). It will be closed if no further activity occurs. Thank you for your contributions to React Apollo!
I can also confirm that the networkStatus is always alternating between 1 and 7 when having the fetchPolicy set to cache-and-network. Is there anyway around having a loading spinner show when for a subsequent fetch? Did anyone find a solution to this?
I am using a workaround until this is fixed. I am querying the cache to see if I have the result cached, if that is the case I don't render the loading spinner:
<Query query={query} fetchPolicy="cache-and-network">
{({ loading, error, data, client, variables }) => {
const { complete } = client.cache.diff({
query: client.cache.transformDocument(query),
variables,
returnPartialData: true,
optimistic: false
});
if (!complete && loading) return <Loading/>;
if (error) return <Error error={error}/>;
return <div>Render data {data}</div>;
}}
</Query>
+1
Please add a different networkStatus to cache-and-network when the data is in the cache.
Rendering a Loading component on networkStatus = 1 makes cache-and-network completely useless, behavior is the same as network-only...
I feel like networkStatus should equal 4 as it is essentially doing a refetch.
No news on this, right? Is there a workaround until resolution?
I have found another funny workaround for the problem:
<Query query={query} fetchPolicy="cache-and-network">
{(networkQuery) => (
<Query query={query}>
{(cacheQuery) => {
if (networkQuery.loading && ! cacheQuery.loading) return <ReLoading />;
if (cacheQuery.loading) return <Loading />;
if (error) return <Error error={error}/>;
return <Data />;
}}
</Query>
)}
</Query>
fetch policy can be either cache-and-network or network-only
@andrei-zhaleznichenka is this better than this: https://github.com/apollographql/react-apollo/issues/1217#issuecomment-389876741?
@mxstbr any news about this? About cache-and-network status code in networkStatus? Still nothing or did I miss some news?
+1
This was addressed in https://github.com/apollographql/apollo-client/pull/4765, and the fix is available in react-apollo 2.5.6. Thanks!
@hwillson Has anyone confirmed that this is working? I still see networkStatus: 1 all the time when the network kicks in despite complete being true.
@declanelcocks Any chance you can put together a small runnable reproduction using 2.5.6?
@hwillson A bit difficult for me to create a runnable reproduction at the moment since it's part of a large app. But anyway, if I log a few things when a cache-and-network query loads, I will get:
1. { networkStatus: 7, complete: true, loading: false }
2. { networkStatus: 1, complete: true, loading: true }
3. { networkStatus: 7, complete: true, loading: false }
I'm getting complete from this (as above):
const cache = result.client.cache.diff({
query: result.client.cache.transformDocument(this.props.query),
variables: this.props.variables,
returnPartialData: true,
optimistic: false
});
My current workaround, as I've seen in older issue threads, is to do the following:
const showCache =
this.props.fetchPolicy !== 'network-only' &&
this.props.fetchPolicy !== 'no-cache' &&
cache.complete;
const loading = showCache ? false : result.loading
There's more to it, but you get the gist. I got the idea from here and also from https://github.com/apollographql/react-apollo/issues/2601 where people came to similar solutions. This is with [email protected].
Does not work for me as well. I鈥檝e created a repo reproducing the problem: https://github.com/marek-saji/react-apollo-1217 using starwars-server.

@hwillson Here is another minimal reproduction:
https://codesandbox.io/s/apollo-cache-network-issue-miren
Using apollo-client 2.6.4.
Seems like this is still an issue as per @kylesuss's reproduction - any news regarding this?
Using hooks:
import { useQuery } from '@apollo/react-hooks';
import gql from 'graphql-tag';
const query = gql` ... `;
const variables = { ... };
const { loading, error, data, client } = useQuery(query, {
variables,
fetchPolicy: 'cache-and-network',
};
// Query the cache
let inCache = true;
if (loading) {
try {
client.readQuery({ query, variables }); // Read from cache. Error thrown if empty
} catch {
inCache = false;
}
}
return (loading && !inCache) ? <Loading /> : <Data />;
Based on previous solutions/workarounds, I have made a custom hook for this situation:
// useApolloCacheQuery.ts
import { useApolloClient } from '@apollo/react-hooks'
import { OperationVariables } from 'apollo-boost'
import { Cache } from 'apollo-cache'
import { DocumentNode } from 'graphql'
/** Custom hook to query the cache to determine if query result exists already */
export default function useApolloCacheQuery<T>(
query: DocumentNode,
variables: OperationVariables,
): Cache.DiffResult<T> {
const { cache } = useApolloClient()
return cache.diff({
query: cache.transformDocument(query),
variables,
returnPartialData: true,
optimistic: false,
})
}
// Component.tsx
// ..
const { data, loading } = useQuery<DataResponse>(query, {
variables,
})
const { complete } = useApolloCacheQuery(query, variables)
return (!complete && loading) ? <Loader /> : <Child />;
// ..
Can we reopen this case?
Still having issues here as well ! Right now you cant really follow the stale-while-revalidate pattern, which makes cache-and-network completely useless. 馃槶
Let's reopen it, I want to use SWR too!
I wrote two custom hooks that are wrappers around useQuery and useLazyQuery and rewrite the loading property in order to enable this behavior. You can find them here: https://gist.github.com/alexvilchis/64a5b07172e8e216c6542f4f4b637cdd
They simply do what @sincospi said: check the cache and set loading to true if it didn't find an entry. I found this to be the solution with less refactoring needed.
Most helpful comment
I can also confirm that the
networkStatusis always alternating between1and7when having thefetchPolicyset tocache-and-network. Is there anyway around having a loading spinner show when for a subsequent fetch? Did anyone find a solution to this?