T
tRPC

❓-help

Is there a way to refetch a query with new parameters?

AAvraj1/23/2024
Hi I'm using tRPC in a Next.js app and I have a button that a user can click to get the latest data from the server. By default this data is cached in the server because the query is expensive. I've added an optional param/input in my query that looks like this:
guilds: privateProcedure
.input(
z
.object({
skipCache: z.boolean().optional(),
})
.optional()
)
.query(async ({ input, ctx }) => {
// Get data
});
guilds: privateProcedure
.input(
z
.object({
skipCache: z.boolean().optional(),
})
.optional()
)
.query(async ({ input, ctx }) => {
// Get data
});
So when { skipCache: true } is set, the user can bypass the cache and get the latest data. I'm feeling a bit lost however when it comes to the implementation itself. I can't find anything in the docs regarding refetching with new/updated params.
const trpcUtils = trpc.useUtils(); // This will return cached data from the server.

const { data: guilds, error } = trpc.private.guilds.useQuery();

const handleRefresh = () => {
// The implementation to bypass cached data => { skipCache: true }
}

return <button onClick={handleRefresh}>Refresh</button>
const trpcUtils = trpc.useUtils(); // This will return cached data from the server.

const { data: guilds, error } = trpc.private.guilds.useQuery();

const handleRefresh = () => {
// The implementation to bypass cached data => { skipCache: true }
}

return <button onClick={handleRefresh}>Refresh</button>
Is this something that's possible?
Solution:
What you can do is just to have a skipCache state and pass this to your useQuery. ```tsx const [skipCache, setSkipCache] = useState(false); ...
Jump to solution
BBeBoRE1/23/2024
If you invalidate the query it will refetch https://trpc.io/docs/client/react/useUtils#query-invalidation
useUtils | tRPC
useUtils is a hook that gives you access to helpers that let you manage the cached data of the queries you execute via @trpc/react-query. These helpers are actually thin wrappers around @tanstack/react-query's queryClient methods. If you want more in-depth information about options and usage patterns for useContext helpers than what we provide h...
BBeBoRE1/23/2024
so
const utils = trpc.useUtils()

utils.private.guilds.invalidate()
const utils = trpc.useUtils()

utils.private.guilds.invalidate()
BBeBoRE1/23/2024
Also you shouldn't skip the cache, it's better to set the time till the data is stale. If the data is stale useQuery will automatically refetch when it's run. You can also set the refetchInterval, so that the data gets refetched every n milliseconds given https://tanstack.com/query/latest/docs/react/reference/useQuery
AAvraj1/23/2024
thanks i've tried this before, but such is the feature. if a user wants the latest data it makes for bad ux to make them wait a certain time. also as mentioned it's an expensive query so it should only be done every now and then, which is why the cache i have on the server lasts 15 mins. is there no workaround at all for this?
BBeBoRE1/23/2024
Ah sorry, had misread your question. I still don't fully understand however. What's the problem with the invalidate method?
AAvraj1/23/2024
so i've used invalidation before, but the reason it doesn't work in my case is that it uses the same query details to make another request to the server. there's no way for me to explicitly state in the invalidation that this specific request is supposed to have a new set of parameters. i was thinking of maybe creating a new route in my server to invalidate the cache and return new data but that leads to 2 routes doing almost the same thing. they'll both return the same data, but one does with cache and one without
BBeBoRE1/23/2024
invalidate() without input invalidates all queries, regardless of input. So invalidate() will invalidate even a query like trpc.private.guilds() and trpc.private.guilds({skipCache: true}). If you only want to invalidate the query where you used a specific input like trpc.private.guilds({skipCache: true}) then you can call utils.private.guilds.invalidate({skipCache: true}) Or do you mean that you first want to do it without cache, and then with cache?
AAvraj1/23/2024
the other way around actually when the page is first loaded, the data that is fetched should be from the cache (if it's available in the server). but the user will now have the chance to fetch the latest data by clicking a button. this button is supposed to invalidate the cache in the server and return the most up to date data imagine a discord bot dashboard where you have a list of servers once a user is in this page, say they create a new server in discord but now that server is not part of the list in the web app because it's still using the cache which will last another 15 mins the refresh button will give them the option to fetch the latest array of servers
Solution
BBeBoRE1/23/2024
What you can do is just to have a skipCache state and pass this to your useQuery.
const [skipCache, setSkipCache] = useState(false);

const {data: guilds} = trpc.private.guilds.useQuery({skipCache});

const utils = trpc.useUtils();

const handleRefresh = () => {
setSkipCache(true);
utils.private.guilds.invalidate();
}
const [skipCache, setSkipCache] = useState(false);

const {data: guilds} = trpc.private.guilds.useQuery({skipCache});

const utils = trpc.useUtils();

const handleRefresh = () => {
setSkipCache(true);
utils.private.guilds.invalidate();
}
AAvraj1/23/2024
alright so i've tried this approach too and there is one slight issue. let me explain. everything works well until the handleRefresh function has stopped calling. say the user wants to refresh the list of guilds once again. the skipCache state is now stuck at true and handleRefresh won't do anything anymore when called changing it back to false at the end of the handleRefresh function doesn't seem to do anything either because of how react handles state changes
BBeBoRE1/23/2024
Why would handleRefresh not do anything after the first refetch? invalidate() will always force a refetch.
AAvraj1/23/2024
you're definitely right there, but there is still an issue of requests sent on behalf of tRPC when focusing on the window. i like that feature but when focusing back on the window it'll send new requests. but now it'll send with skipCache set to true because the state still hasn't changed back to false
BBeBoRE1/23/2024
And you want to keep refetchOnWindowFocus enabled?
AAvraj1/23/2024
it would be nice to have that, but if i can keep that turned off i believe that fixes the issue right? tRPC doesn't send any other requests automatically i'm guessing?
BBeBoRE1/23/2024
Yes, setting that to false disables that behavior. If you do want to keep it enabled, you might just need to use the queryClient manually and then update the queryKey yourself manually like you would when doing an optimistic update. If you understand what I mean.
AAvraj1/23/2024
i think for now i'll disable refetchOnWindowFocus. in case i find a reason for it to be enabled i'll have to do a little more research on using the queryClient xD i believe that solves the issue for me

Looking for more? Join the community!

Recommended Posts
Multiple Routers with WebsocketsHi. I am looking to create two routers with either the same websocket connection or two unique websoIs there any benefit to putting the db connection in the context versus having it as an global var?Can I do this? ```ts export const challengesRouter = router({ getChallengeById: privateProcedure Controller is already closed crashIm using trpc with nextjs 14 app router and started to see that my app crashes due to such error. DiThis page needs to bail out of prerendering at this point because it used revalidate: 0I've been testing out partial prerendering with next using tRPC but having some issues. Everytime How to infer query types on client?```ts export const tenantRouter = router({ getTenants: procedure.query(() => { return { hello:NextJS Output TypingsQuick question probably stupid, I learned about this library yesterday and completely migrated from 'react-server-dom-webpack/client' errorHey, i am trying to get started with TRPC but getting this error ```shell ../../node_modules/.pnpm/React Query client errors on 401I'm throwing a `TRPCError({ code: "UNAUTHORIZED" })` in a middleware, and handling error states retuExtremely slow queriesI'm having elapsed time of 2 to 5 seconds and I just switched from mongo to postgres. Is it the DB lTRPC works but getting unpredictable Typescript warnings for a barebones trpc monorepo projectHi, TRPC is working as expected but there are many warnings that feels very "off" for simple proceduKirimase's tRPC usage CRUD routeHey, using Nico's Kirimase tRPC package. I am trying to call the queries and mutations, in the db/scClient `tsc` checking server codeI have a trpc server and vite/react client set up in a pnpm monorepo. The VSCode type checking is beUnable to set up a client side subscription to a trpc route that supports websocketsI wrote the code on the client side here to query the subscription: https://github.com/sumanthneerumwhat's this union type doing(Zod)?I have 2 types of user, guest and registered(schemas). I have a union type with both and the guest dtrpc's useQuery with undefined input adds extra {"values":["undefined"]} to queryMy React app has several calls to query endpoints that have no input data but that do need useQuery Can you ensureData without the useUtils hook?The Tanstack Router docs recommend calling `ensureQueryData` in a route’s loader function if using THelp with queries vs mutationssuper basic question here from a newb to trpc...i see the calls are basically split into two type, qInterceptor in serverHow can I make an interceptor to get all the results before they are sent to the client, can I do thCan't do server side data fetching with RSC.Whenever I try to use a proxy client to fetch data in a React Server Component with Nextjs14, I get v10, passing useQuery options, queryKey mandatory?I have a simple query like this ```javascript const me = api.user.me.useQuery(undefined, { ena