Tom
Tom12mo ago

How to prefetch data on the client into the cache?

To simplify a bit, lets say I'm making an app that allows users to view a project. I have a top level UI route with a summary of the project and then sub-routes that display more details, some of which require more fetches. Is there a way that I can make it so that when the top-level route loads, the trpc cache automatically prefetches the data needed for the sub-routes? Whenever I search the site for 'prefetch', I find the SSR stuff, but I'm actually trying to prefetch on the client. Thanks.
6 Replies
schlabach
schlabach12mo ago
I'm dealing with the same issue (https://discord.com/channels/867764511159091230/1121910827335831674). According to the docs, you should be able to use trpc.useContext() for this:
const utils = trpc.useContext()

utils.subRoute.prefetch({...inputs})
const utils = trpc.useContext()

utils.subRoute.prefetch({...inputs})
However, this prefetch() isn't being picked up by React Query and the data isn't being cached. Inspecting Chrome's devtools reveals that the fetch is being made, but it doesn't seem like React Query is picking up on that. https://trpc.io/docs/client/react/useContext Lmk if you have any success with this.
Tom
Tom12mo ago
ill give it a try. thanks a lot. (sorry went away for a couple days) just tried this.... is there a way to make it prefetch only if there is nothing in the cache from that route? i got it to work. let me know if you figure out anything different
/* prefetch queries for subroutes */
useEffect(() => {
if (!uid || !creatorID) return;
if (creatorID !== uid) return;

const cachedSettingsData = trpcUtils.ui.getTournamentSettingsView.getData({ tournamentID });
if (!cachedSettingsData) trpcUtils.ui.getTournamentSettingsView.prefetch({ tournamentID });

const cachedOverlaysData = trpcUtils.overlays.getCustomOverlays.getData();
if (!cachedOverlaysData) trpcUtils.overlays.getCustomOverlays.prefetch();
}, [trpcUtils, tournamentID, creatorID, uid]);
/* prefetch queries for subroutes */
useEffect(() => {
if (!uid || !creatorID) return;
if (creatorID !== uid) return;

const cachedSettingsData = trpcUtils.ui.getTournamentSettingsView.getData({ tournamentID });
if (!cachedSettingsData) trpcUtils.ui.getTournamentSettingsView.prefetch({ tournamentID });

const cachedOverlaysData = trpcUtils.overlays.getCustomOverlays.getData();
if (!cachedOverlaysData) trpcUtils.overlays.getCustomOverlays.prefetch();
}, [trpcUtils, tournamentID, creatorID, uid]);
Alex / KATT 🐱
Alex / KATT 🐱11mo ago
There's ensureData that does that
Tom
Tom11mo ago
ensureData() seemed to refetch every time the useEffect was run even if the data was already prefetched With unfortunately meant that every page navigation it would fetch again which is unnecessary for my app Like it would refetch even if I was going to a route that didn’t require this data
Alex / KATT 🐱
Alex / KATT 🐱11mo ago
Might be that the data is stale Check the react query docs about ensureData
Tom
Tom11mo ago
Ok. I’ll try that later. Oh I just realized i wasn’t providing the right query when I tried ensure Data I only fixed it after I changed to the code I have above. That was probably the problem. Thanks Right query params*