apollo-client
apollo-client copied to clipboard
No difference beetween `cache-and-network` and `network-only` strategies!
I think the cache-and-network strategy doesn't work properly and acts similar to network-only.
What To Expect
- apollo sends two queries to cache and network in parallel.
- if doesn't exist in cache waiting for network and store in cache for next query.
- if exists, render data and wait for network in background for syncing data.
but in step 3 :
apollo doesn't render cache data Immediately until network data is received. This is not fast and behaves like network-only strategy.
have noticed this as well; seems like there should be another exposed boolean like refetching or something so loading isn't used when there is relevant data in the cache and the network request is running in the background
This is the solution we are using to expose a refetching prop so we can control rendering behaviour better @wminshew @foad-salawati
import type { OperationVariables, QueryResult } from "@apollo/react-common";
import type { QueryHookOptions } from "@apollo/react-hooks";
import { useQuery as useApolloQuery } from "@apollo/react-hooks";
import type { DocumentNode } from "graphql";
export function useQuery<TData = any, TVariables = OperationVariables>(
query: DocumentNode,
options?: QueryHookOptions<TData, TVariables>,
): QueryResult<TData, TVariables> & {
refetching: boolean;
} {
const response = useApolloQuery<TData, TVariables>(query, options);
return {
...response,
refetching: response.networkStatus === 4,
};
}
Then you can do
const { refetching } = useQuery(aQueryDocument);
I know it's not a real solution to the issue, but maybe it helps as a patch
Also have this problem, cache-and-network is not loading from cache first
@foad-salawati did you find a workaround?
@foad-salawati did you find a workaround?
Not yet! follow this opened issue #1781 for some solutions or a new released in the future.
I just saw that if you use notifyOnNetworkStatusChange: true it works for me and does return the cached data on the first return
I just saw that if you use
notifyOnNetworkStatusChange: trueit works for me and does return the cached data on the first return
using both notifyOnNetworkStatusChange: true and fetchPolicy: 'cache-and-network', didn't solve the issue
using both notifyOnNetworkStatusChange: true and fetchPolicy: 'cache-and-network', didn't solve the issue
Neither with my setup:
"@apollo/client": "^3.10.4"
using both
notifyOnNetworkStatusChange: trueandfetchPolicy: 'cache-and-network',didn't solve the issue
still happening. didn't work with my setup too:
"@apollo/client": "^3.10.4",
"apollo-angular": "^7.0.1",
This was really annoying me too, but I think I finally have a solution.
The problem is that that, even though data gets the cached value immediately, the loading state still gets set to true while the additional network request is running. And so if you're rendering a "Loading" component based on loading, then you won't see the new data.
The solution is to check both the data and the loading state before rendering your "Loading" UI.
const {data, loading, error } = useQuery ( {variables, fetchPolicy: 'cache-and-network' });
if (loading && !data) return <LoadingComponent />
return <DataComponent data={data} />
This is working for me -- I get the cached result immediately when there is one, and a Loader when there isn't any cache available (and the UI gets updated when new data comes in from the network request, as expected).
Found a temporary solution which is simulating cache-and-network somehow, just set fetchPolicy: 'cache-first', and also do ref.refetch(); whenever a "query" gets send to the server. Actually this is not the way I like but the REAL cache-and-network is not working.
query<T = any, V extends Record<string, any> = {}>(query: DocumentNode, variables?: V, fetchPolicy: WatchQueryFetchPolicy = 'cache-and-network'): GeneralQueryType<T, V> {
const ref = this.apollo.watchQuery<T, V>({
query,
variables,
context: this.context,
fetchPolicy: 'cache-first',
refetchWritePolicy: 'overwrite',
});
const obs = ref.valueChanges.pipe(
filter(result => result.networkStatus === NetworkStatus.ready),
map(response => response.data));
// NOTICE :: temporary workaround
ref.refetch();
return {
obs,
ref
};
}
Turns out apollo won't be able to cache previous results correctly depending on your query and whether it has field called id, you will need to set type policies so the query results can be properly normalised and saved in cache.
https://www.apollographql.com/docs/react/caching/cache-configuration/
This worked for me after setting those type policies, use the apollo client devtool to check your query results and see if they have been cached.
Hopefully this helps someone out there.