W
Wasp•5mo ago
neogeofun

React Query questions

How are the cache keys handled under hood? Let's say I visited a page where user has a list of favorite items. Then the user visits an item's page. On this page, I could access the cache and if the item is in the list save an API call. But I couldn't access the query cache key. So I checked React Dev Tools, went to QueryClientProvider on components and checked client. QueryCache element is there; so clicked on it and found that it only contains the most recent page's queries cached. If I am on favorites page it will be something like: 1. ["auth/me"] 2. ["favorites-endpoint-url"] And if I go another page, "favorites-endpoint-url" won't be in the cache keys anymore. Instead Is there a bug? Or is there something that I should be doing other than providing the query function and data to useQuery (I thought cache key creation was handled by Wasp)? Or am I just looking at the wrong place?
10 Replies
kapa.ai
kapa.ai•5mo ago
Hi @neogeofun. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- In Wasp, the cache keys are handled internally and are not expected to be supplied by the user. This is done by the useQuery hook, which is a thin wrapper around the useQuery hook from react-query. The useQuery hook from Wasp accepts three arguments: queryFn, queryFnArgs, and options. The queryFn is the client-side query function generated by Wasp based on a query declaration in your .wasp file. The queryFnArgs is the arguments object (payload) you wish to pass into the Query. The options is a react-query options object, which you can use to change the default behavior for this particular Query (source (https://wasp-lang.dev/docs/data-model/operations/queries#the-usequery-hook-1)). If you need to access the Query cache key, you can do so by accessing the queryCacheKey property on any Query. Here is an example:
import { getTasks } from 'wasp/client/operations'

const queryKey = getTasks.queryCacheKey
import { getTasks } from 'wasp/client/operations'

const queryKey = getTasks.queryCacheKey
(source (https://wasp-lang.dev/docs/data-model/operations/actions#advanced-usage)) As for the issue you're experiencing with the cache keys, it's hard to say without more information. It could be that the cache is being invalidated or updated in a way that's causing the "favorites-endpoint-url" to be removed. There are several ways to invalidate/update the cache in Wasp, including directly (via the cache key or methods returned by useQuery), or via Resources (where each operation defines which resources it works with, and when an action using a resource is done, all queries using that resource need to be refetched) (source (https://github.com/wasp-lang/wasp/issues/63)). If you're still having trouble, I would recommend checking out the Wasp Discord (https://discord.com/channels/686873244791210014/1222460717136085054) or opening an issue on the Wasp GitHub (https://github.com/wasp-lang/wasp/issues). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @neogeofun, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
neogeofun
neogeofunOP•5mo ago
Okay, this was handy. Using queryKey, I can see the items saved in cache. Not sure why React Dev Tools, QueryClientProvider is missing some queries though. Maybe they just display most recent queries after a route is mounted. I take above back; if I go to the list of favorites, and then click a favorite, I can get the cached value. However, if I go to another page, like list of items, and then click an item the same page will return undefined for the following code:
const queryK = getAllFavoritesByUser.queryCacheKey;
const queryClient = useQueryClient()
const queryCache = queryClient.getQueryCache();
const query = queryCache.find(queryK);
console.log(queryK)
console.log(query);
const queryK = getAllFavoritesByUser.queryCacheKey;
const queryClient = useQueryClient()
const queryCache = queryClient.getQueryCache();
const query = queryCache.find(queryK);
console.log(queryK)
console.log(query);
In any case, I will make this an API call on the item page to find if user favorited it. It is a cheap call. But how do I make sure that React Query is in fact working properly and saving me API calls for more expensive calls? Like list of items with filters for example; no reason to call the server every time the user visits this page. On the same vein, is there a way to set the cache duration? Because I know this list page won't be changing daily. I'd be happy to return values from the cache for hours or days, not minutes. @kapa.ai feel free to pitch in buddy.
kapa.ai
kapa.ai•5mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- React Query provides a mechanism to control the cache duration and stale time of your queries. This can be done by setting the staleTime and cacheTime options in the useQuery hook. The staleTime option determines how long the fetched data is considered fresh. If a component remounts (or a new component mounts) and the stale time has not been reached, the query function will not be executed and the cached result will be returned instead. If the stale time is set to Infinity, the data will never become stale and the query function will not be executed on component remounts. The cacheTime option determines how long the unused data is kept in the cache. If a query's data is not used for longer than this time, it will be garbage collected. Here is an example of how you can set these options:
const { data: tasks } = useQuery(getTasks, { id }, {
staleTime: 1000 * 60 * 60 * 24, // 24 hours
cacheTime: 1000 * 60 * 60 * 24 * 7, // 7 days
})
const { data: tasks } = useQuery(getTasks, { id }, {
staleTime: 1000 * 60 * 60 * 24, // 24 hours
cacheTime: 1000 * 60 * 60 * 24 * 7, // 7 days
})
In this example, the data returned by the getTasks query will be considered fresh for 24 hours and will be kept in the cache for 7 days if not used. Please note that these options are provided by React Query and not Wasp. Wasp uses React Query under the hood for data fetching and caching, and it provides a thin wrapper around the useQuery hook from React Query. This means that you can use all the options and features provided by React Query in your Wasp app. For more information, you can check out the React Query documentation (https://react-query.tanstack.com/guides/important-defaults) and the Wasp documentation (https://wasp-lang.dev/docs/data-model/operations/queries#the-usequery-hook-1). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @neogeofun, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
neogeofun
neogeofunOP•5mo ago
doumo arigato mr. robotto Alright, @kapa.ai my main man, I did use staleTime and cacheTime with 24/7 limits above. But when I visit the page, it still hits the server even though filters and the route are the same. What is up with that?
kapa.ai
kapa.ai•5mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- If you're still seeing API calls being made despite setting staleTime and cacheTime, it could be due to a few reasons: 1. Cache Invalidation: React Query automatically refetches data when the window is refocused or when the network is reconnected. This behavior can be controlled using the refetchOnWindowFocus and refetchOnReconnect options. If you want to disable this behavior, you can set these options to false:
const { data: tasks } = useQuery(getTasks, { id }, {
staleTime: 1000 * 60 * 60 * 24, // 24 hours
cacheTime: 1000 * 60 * 60 * 24 * 7, // 7 days
refetchOnWindowFocus: false,
refetchOnReconnect: false,
})

const { data: tasks } = useQuery(getTasks, { id }, {
staleTime: 1000 * 60 * 60 * 24, // 24 hours
cacheTime: 1000 * 60 * 60 * 24 * 7, // 7 days
refetchOnWindowFocus: false,
refetchOnReconnect: false,
})

2. Cache Key Changes: React Query uses the queryFn and queryFnArgs to generate a unique cache key for each query. If these values change between renders, a new cache entry will be created and the query function will be executed again. Make sure that the queryFn and queryFnArgs are stable between renders. 3. Cache Garbage Collection: React Query automatically removes unused data from the cache after a certain period of time (defined by cacheTime). If the data is not used for longer than this time, it will be garbage collected and the query function will be executed again when the data is needed. If none of these reasons apply, it might be a bug or a misconfiguration. In that case, I would recommend reaching out to the Wasp community on Discord (https://discord.com/channels/686873244791210014/1222460717136085054) or opening an issue on the Wasp GitHub (https://github.com/wasp-lang/wasp/issues) for further assistance. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @neogeofun, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
neogeofun
neogeofunOP•5mo ago
OK @kapa.ai this better works, or I will beat you with a stick
kapa.ai
kapa.ai•5mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- I'm here to help, so let's make sure everything works as expected! If you're still encountering issues, don't hesitate to ask for further assistance. Remember, you can always reach out to the Wasp community on Discord (https://discord.com/channels/686873244791210014/1222460717136085054) or open an issue on the Wasp GitHub (https://github.com/wasp-lang/wasp/issues) for more detailed help. Happy coding! ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @neogeofun, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
neogeofun
neogeofunOP•5mo ago
Heads up; TanStack v5 changed cacheTime property to gcTime: Wasp is on v4 but something to keep in mind, also me providing this config object to my useQuery still doesn't prevent server calls:
staleTime: 1000 * 60 * 60 * 24, /* 24 hours */
cacheTime: 1000 * 60 * 60 * 24 * 7, // 7 days
refetchOnWindowFocus: false,
refetchOnReconnect: false,
staleTime: 1000 * 60 * 60 * 24, /* 24 hours */
cacheTime: 1000 * 60 * 60 * 24 * 7, // 7 days
refetchOnWindowFocus: false,
refetchOnReconnect: false,
MEE6
MEE6•5mo ago
Wohooo @neogeofun, you just became a Waspeteer level 5!
miho
miho•5mo ago
@sodic check this out when you have the time 🙂
Want results from more Discord servers?
Add your server