Cache as Backup but cache is never used
I wanted to use React Query to:
1) Cache data so it gets only retrieved from the backend every 5 min and no requests are wasted
2) Use Cached data if the internet connection is lost
This is how I setup my client:
And this is how i use my api for testing atm just a GET Request with all data from my backend
However for some reason it ALWAYS seems to retrieve from the backend and also when the connection is lost it just pauses the query. What am I doing wrong?
I also set up so it know when its online like shown in the docs
Here a demonstration of my issue
https://youtu.be/R27mCA9-IuU
28 Replies
foreign-sapphire•9mo ago
It seems to work correctly in your video, when you are initially going to the page, it does not seem to make a new request, hence using the cache, but then you refresh the screen which calls
refetch, which forces a new request to be made
You might be able to replace refetch with queryClient.ensureQueryData with the revalidateIfStale: true option.
and also when the connection is lost it just pauses the queryThe query might get paused, but check if the
data property is available. I think it should have the last data that is in the cache.graceful-beigeOP•9mo ago
oh so refetch does a completly refetch no matter what the state of the data is?
foreign-sapphire•9mo ago
Yes
graceful-beigeOP•9mo ago
i just wanted to trigger some kind of refresh to be able to tell if the cache is working
the switching of the tabs does not trigger a remount thats why i wanted to use refetch
foreign-sapphire•9mo ago
useQuery is like a subscriber to the cache, it subscribes to changes to a query from the cache and takes it's value from there when it changes. When you refetch/invalidate a query, it will retrigger the queryFn and replace the data.
with ensureQueryData with the revalidateIfStale option, it will only update the query's data if it is "stale"
If it is still fresh (3 mins have not passed yet), it will not refetch it, the ensureQueryData function will just return the data from the cache
Also, if you are wondering how it works, if the query is stale, ensureQueryData will replace the data in the cache. As useQuery is subscribed to the cache, it's data will change to the new value from the cache, hence causing a rerender in your component.graceful-beigeOP•9mo ago
Ok so if I do it like this its working just as you said! Is this the correct way of doing it?
now only this is the question if its working
foreign-sapphire•9mo ago
Why do you need the
isRefreshing state? Your query has isFetching/isRefetching
those states will also update
Just check if you have data while the query is paused, I think you should do, but I am not sure eithergraceful-beigeOP•9mo ago
to use inside the
refreshControl
foreign-sapphire•9mo ago
Try using
isRefetching from the query, I am quite positive it should work
useQuery subscribes to the entire state of the query. Hence all properties will update if neededgraceful-beigeOP•9mo ago
seems to be working! Thank you
i am just unsure about the data when the device is offline, its hard to test since i cant restart the application without having connection
foreign-sapphire•9mo ago
inline the query data in the screen in a
Text component, using JSON.stringify (if it is JSON). Stop your emulator's internet, and try testing if the data is there when you go to the screen.
You wont get logs anymore, but you can see in the screen if the data is there
I am yet to find a better way to test offline functionality in RN toograceful-beigeOP•9mo ago
i will try
Can i somehow force the expo-router tabs to force refresh when i switch tabs?
foreign-sapphire•9mo ago
You can also see this
https://stackoverflow.com/a/47046171
I guess, the emulator gets proxied your internet connection, but it really only requires LAN for development
graceful-beigeOP•9mo ago
lmao so just cutting my pcs internet connection
I guess that should work
foreign-sapphire•9mo ago
I love how I usually find cool stuff that I needed a long time ago when I am trying to help others, but when I have to fix my own issues I dont 🙃
graceful-beigeOP•9mo ago
at least you were able to solve my issue 😄
but you have any idea about this?#
foreign-sapphire•9mo ago
You could likely use this instead:
https://tanstack.com/query/latest/docs/framework/react/react-native#refresh-on-screen-focus
I am not sure, but I think you can import
useFocusEffect from expo-router instead, even though both should work fine
Also, look at the section below too ("Disable queries on out of focus screens"), you might want that
react-navigation, and expo-router implicitly as it is just a wrapper over react-navigation, by default keep screens rendered below the current one. So it just reuses them, which is useful for performance.
Not sure how it does it for tabs, but afaik Stacks are literally screens that get layered one upon another (useful when you have a transparent modal screen that shows the screen that's under it)
You can also look at the unmountOnBlur option from react-navigation, which will make screens unmount when not focused
Then, when you go back to that screen, it will remount and retrigger everything
I do recommend you to avoid it tho, for performance reasonsgraceful-beigeOP•9mo ago
this does not work in the expo router tho
yeah i just want to use it for testing
since when i remount and got no connection it should just pull the data out of the cache and i could see it that way
foreign-sapphire•9mo ago
rather just implement screen focus refreshing
Just copy that hook from the docs, and when calling it, pass it your refresh function that uses
ensureQueryData
you'd anyway want it for the appgraceful-beigeOP•9mo ago
this honestly confuses me a bit 😄 i am quite new to react native tho
foreign-sapphire•9mo ago
useFocusEffect is called when the screen it is called from is focused/unfocused (aka if the user is on that screen)
you want to call your refresh function when that happens
graceful-beigeOP•9mo ago
I see, but from where do i call this?
like from where does my screen know it is focused or not?
foreign-sapphire•9mo ago
You have to add it everywhere where you have a query that needs to refresh on screen focus
ex:
graceful-beigeOP•9mo ago
Shouldnd
refetchOnWindowFocus / refetchonMount do this automatically?
or am I missing the point here?foreign-sapphire•9mo ago
refetchOnWindowFocus is a browser thing
what is a window in react-native?graceful-beigeOP•9mo ago
i would "guess" when you switch to another app and come back? but not sure
foreign-sapphire•9mo ago
Well yeah, but remember, react-navigation keeps screens you've been to in the background, they never unmount. When you go back to a screen you already been to, it just shows it on top. So hooks/rendering does not happen again.
So, you also want to refresh on screen change
you might be able to use the focusManager for this, but I am not sure actually, no, it wont work
but yeah, you are missing the point,
refetchOnWindowFocus + focusManager only refreshes when you put your app in the background and you come back to it, for in-app screen changes you need to use the "refresh on screen focus" approachgraceful-beigeOP•9mo ago
i will try to look this up and understand this 😄
but since implementing the react query my build in the app just shows a white screen shich is not so good