T
TanStack•2y ago
constant-blue

Offline Cache Not Working with UseSuspenseQuery

Hello! Im trying to test my apps offline capabilities and I'm having two issues: 1. I have gctime set to a really long time along with the persistor setup (code at the bottom). When I simulate offline mode in the devtools and refresh the page, everything is fine. The app loads the old data and tries to make requests. When the requests fail though, the queries get ejected out of localstorage, and when I refresh for the second time, I get an error thrown 2. I'm using react-query + trpc. For some reason when the queries fail they throw an exception outside of react query. Is this because I'm using suspense queries? I'd like for it to ignore as if its nothing happened if the request fails (assuming there is old data). Here is a sample stack trace
TRPCClientError-0de4d231.mjs:38 Uncaught TRPCClientError: Failed to fetch
at TRPCClientError.from (TRPCClientError-0de4d231.mjs:38:16)
at httpUtils-f58ceda1.mjs:129:17
TRPCClientError-0de4d231.mjs:38 Uncaught TRPCClientError: Failed to fetch
at TRPCClientError.from (TRPCClientError-0de4d231.mjs:38:16)
at httpUtils-f58ceda1.mjs:129:17
This might be connected to the second refresh of #1 so ill retry after figuring that out Code:
const persistOptions: Omit<PersistQueryClientOptions, 'queryClient'> = {
persister: asyncStoragePersister,
};

export const queryClient = new QueryClient({
queryCache: new QueryCache({
onError(error, query) {
logger.error(`[${query.queryKey.toString()}] error: `, error.message);
Sentry.captureException(error, {
extra: {
queryKey: query.queryKey,
},
});
},
}),
defaultOptions: {
queries: {
gcTime: ms('1 day'),
refetchOnWindowFocus: false,
retry: false,
// throwOnError: false,
// placeholderData: keepPreviousData,
},
},
});
const persistOptions: Omit<PersistQueryClientOptions, 'queryClient'> = {
persister: asyncStoragePersister,
};

export const queryClient = new QueryClient({
queryCache: new QueryCache({
onError(error, query) {
logger.error(`[${query.queryKey.toString()}] error: `, error.message);
Sentry.captureException(error, {
extra: {
queryKey: query.queryKey,
},
});
},
}),
defaultOptions: {
queries: {
gcTime: ms('1 day'),
refetchOnWindowFocus: false,
retry: false,
// throwOnError: false,
// placeholderData: keepPreviousData,
},
},
});
9 Replies
constant-blue
constant-blueOP•2y ago
Hmmm I just noticed that the react query example does not make a request when the offline simulator is on in devtools but it does in my app my network mode is either online or offlineFirst This has me stumped i swear react query used to not make requests if the network was offline, but im seeing it make a bunch of requests with v5 when the devtools simulate offline or wifi is off This might be a problem with the TRPC client 🤔 Looking at their source code they dont really do much though so maybe/maybe not
constant-blue
constant-blueOP•2y ago
I looked at a useQuery that I have (stripe.pricing) and I see it making a request even with offline triggered in chrome devtools. I see the following state in the react query tools as well. Interestingly it never goes to the "paused" state when i click refetch
No description
No description
constant-blue
constant-blueOP•2y ago
Interesting revelation!! I did window.onlineManager = onlineManager, and started playing with the different states. 1. I load the page, go to the screen that has useQuery, then go back, turn network throttling to offline, and go to the screen again. In the RQ Devtools, I see that the query is puased, perfect! window.onlineManager.#online = false 2. (Broken). I refresh the page with offline, and immediately see a bunch of requests failed. I go to the screen I want, I see the old data from the storage BUT I also see a failed request. I refresh the page again and my application throws because the data is no longer in the stroage due to the failed request from before. Here is the problem: window.onlineManager.#online = true! Is this a bug? https://tanstack.com/query/latest/docs/react/reference/onlineManager I see the change in the top of the docs now... 🤦 Not quite there yet, I added onlineManager.setOnline(navigator.onLine); and that seems to work but now when I refresh the page, the first query is stuck on inactive I tried both networkModeonline where it gets stuck in inactive and offlineFirst which tries to make a network request and then throws (which wipes it from the query cache from localstroage) Im curious as to why with offlineFirst it tries to make the query instead of pausing and returning the cached data gcTime and staleTime are really high numbers
constant-blue
constant-blueOP•2y ago
Proof
No description
constant-blue
constant-blueOP•2y ago
Lord knows what I did but finally got it working I realy have no idea what changed... Wooo I actually narrowed it down to
dehydrateOptions: {
shouldDehydrateQuery(query) {
const defaultResponse = defaultShouldDehydrateQuery(query);
const isStorable = query.meta?.storable !== false;

return defaultResponse && isStorable;
},
},
dehydrateOptions: {
shouldDehydrateQuery(query) {
const defaultResponse = defaultShouldDehydrateQuery(query);
const isStorable = query.meta?.storable !== false;

return defaultResponse && isStorable;
},
},
constant-blue
constant-blueOP•2y ago
GitHub
gcTime has a 32 bit limit · Issue #6513 · TanStack/query
Describe the bug I was trying to set the gcTime to 30 days and was noticing all sorts of bugs. Seems like it has a 32 bit integer limit Your minimal, reproducible example https://codesandbox.io/p/d...
constant-blue
constant-blueOP•2y ago
^ this made it particularly hard to debug
absent-sapphire
absent-sapphire•2y ago
absent-sapphire
absent-sapphire•2y ago
hi @TkDodo 🔮 , I am using React-Query in my react-native application. I want to make react-native first offline application. I am getting a problem and you are the best person who can guide me. Problem Scenario :- I have use useQuery to get data and useMutation to post data(optimistic updates add one more field and update ui using onMutate method , if request failed it rollback to previous data) Now i goes to offline mode in my application and add some more field and then i quit my application(cleared from ram) then it rollback to previous data( cache and stale time is infinity). problem is that in that case mutation fails. In rest of all cases mutation continues to resume (until and unless i will not remove application from primary memory / kill app). Please have a look and help me resolve this issue I have wrapped whole code using <PersistQueryClientProvider persistOptions={{persister}} onSuccess={() => { //it will call on mounting // console.log('will get called on re-mounting'); queryClient.resumePausedMutations().then(() => { //it will resume console.log('resumed paused mutations'); queryClient.invalidateQueries(); //it will revalidate queries }); }} client={queryClient}></PersistQueryClient> const queryClient = new QueryClient(); const persister = createAsyncStoragePersister({ storage: AsyncStorage, throttleTime: 3000, });

Did you find this page helpful?