T
TanStack•16mo ago
optimistic-gold

How to refetch queries when the data are comming from the loader

I've a route where I load some fetch some data from react-query, however if I then do a mutaion and refetch that query it doesn't re-render the data in this component, I expect that the loader is only run on mount? How should I go about this?
export const Route = createFileRoute("/_authenticated/dashboard")({
component: Dashboard,

loader: async ({ context: { queryClient, supabase } }) => {
const jwt = await (supabase as SupabaseClient).auth
.getSession()
.then((session) => session.data.session?.access_token);
console.log("jwt", jwt);
return {
activities: await queryClient.ensureQueryData(postsQueryOptions(jwt)),
authToken: jwt,
};
},
});

function Dashboard() {
const { activities, authToken } = Route.useLoaderData();
export const Route = createFileRoute("/_authenticated/dashboard")({
component: Dashboard,

loader: async ({ context: { queryClient, supabase } }) => {
const jwt = await (supabase as SupabaseClient).auth
.getSession()
.then((session) => session.data.session?.access_token);
console.log("jwt", jwt);
return {
activities: await queryClient.ensureQueryData(postsQueryOptions(jwt)),
authToken: jwt,
};
},
});

function Dashboard() {
const { activities, authToken } = Route.useLoaderData();
3 Replies
graceful-blue
graceful-blue•16mo ago
You can invalidate the router, but I wouldn't combine loaderData when you also use react query Check out the examples - they only use the loaders to fill the cache, then always useSuspenseQuery in component
unwilling-turquoise
unwilling-turquoise•16mo ago
Additionally, I would put the jwt bit into beforeLoad (probably in the /_authenticated layout route) so you can throw a redirect if the user is not authenticated. You can then return the token in beforeLoad and it will be part of the context in the child route loader methods. @TkDodo 🔮 One question which I have which is related to this, what is the difference between
const dataOptions: queryOptions({
queryKey: ['test'],
queryFn: () => 'test'
});

// 1. ensureQuery + useLoaderData
const Route = createFileRoute('/data', {
loader: async ({ context: { queryClient } }) => {
return {
data: await queryClient.ensureQuery(dataOptions),
};
},
component: () => {
const { data } = useLoaderData()
return <div>{data}</div>
}
});

// 2. prefetchQuery + useSuspenseQuery
const Route = createFileRoute('/data', {
loader: ({ context: { queryClient } }) => {
void queryClient.prefetchQuery(dataOptions)
},
component: () => {
const { data } = useSuspenseQuery(dataOptions);
return <div>{data}</div>
}
});
const dataOptions: queryOptions({
queryKey: ['test'],
queryFn: () => 'test'
});

// 1. ensureQuery + useLoaderData
const Route = createFileRoute('/data', {
loader: async ({ context: { queryClient } }) => {
return {
data: await queryClient.ensureQuery(dataOptions),
};
},
component: () => {
const { data } = useLoaderData()
return <div>{data}</div>
}
});

// 2. prefetchQuery + useSuspenseQuery
const Route = createFileRoute('/data', {
loader: ({ context: { queryClient } }) => {
void queryClient.prefetchQuery(dataOptions)
},
component: () => {
const { data } = useSuspenseQuery(dataOptions);
return <div>{data}</div>
}
});
my initial guess is that parent routes could render while data is loading in prefetchQuery + useSuspenseQuery, but I just want to make sure my understanding is right 🙂
graceful-blue
graceful-blue•16mo ago
There is no subscription to the query without useQuery / useSuspenseQuery So no refetches and query can be garbage collected because it's seen as unused

Did you find this page helpful?