T
TanStack•4mo ago
other-emerald

Is beforeLoad supposed to run in this situation?

Hi! In my __root.tsx file, I check a session against my auth server in beforeLoad so I can update the router context. In a sub route, if I go from /a to /b, is there a way to preserve the context without having to re-run the root beforeLoad hook? (or any parent beforeLoad hook really) For context, my issue is that currently it's very slow because it makes a ton of requests for every page change
9 Replies
foreign-sapphire
foreign-sapphire•4mo ago
https://discord.com/channels/719702312431386674/1370349635129839616 same behaviour is in the official DIY Auth example I guess Tanstack Query is the way to go
other-emerald
other-emeraldOP•4mo ago
Alright thanks!
foreign-sapphire
foreign-sapphire•4mo ago
I'm still looking for a better solution - if I find anything - I will post it here
other-emerald
other-emeraldOP•4mo ago
Thanks mate fwiw it was slow because i used prefetchQuery instead of ensureQueryData from query
optimistic-gold
optimistic-gold•4mo ago
I posted a comment about this yesterday: https://github.com/TanStack/router/issues/3997#issuecomment-2859050993. While the issue itself is a bit uhhh, poorly worded, it does raise a valid point that's similar to yours, and I've been struggling with it as well this week
GitHub
Performance is horrible when using recommended Authentication patte...
Which project does this relate to? Router Describe the bug When using the recommended patterns for authentication, particularily in tanstack start, the performance of the app is garbage. because on...
optimistic-gold
optimistic-gold•4mo ago
For now I resorted to @tanstack/react-query, code looks a bit like this:
export const Route = createFileRoute('/_authed')({
component: RouteComponent,
context: ({ context: { authClient } }) => ({
queryOptions: {
session: queryOptions({
staleTime: 1000 * 15,
queryKey: queryKeys.core.session(),
queryFn: async () => {
const isAuthenticated = await authClient.isAuthenticated();

return {
isAuthenticated,
sessionUser: isAuthenticated ? await getSessionUserClaimData(authClient) : null
};
}
})
}
}),
loader: async ({ context: { queryClient, queryOptions } }) => {
// We're using `fetchQuery` because `ensureQueryData` would ignore the
// staleTime and never refresh the query, while we want to periodically
// recheck the session so we can send the user to login if necessary.
const session = await queryClient.fetchQuery(queryOptions.session);

if (!session.isAuthenticated) {
// Redirect login here
}
}
});

function RouteComponent() {
const { queryOptions } = Route.useRouteContext();
const queryResult = useSuspenseQuery(queryOptions.session);

if (queryResult.data.isAuthenticated) {
return (
<SessionUserContext value={queryResult.data.sessionUser}>
<Outlet />
</SessionUserContext>
);
}

return null;
}
export const Route = createFileRoute('/_authed')({
component: RouteComponent,
context: ({ context: { authClient } }) => ({
queryOptions: {
session: queryOptions({
staleTime: 1000 * 15,
queryKey: queryKeys.core.session(),
queryFn: async () => {
const isAuthenticated = await authClient.isAuthenticated();

return {
isAuthenticated,
sessionUser: isAuthenticated ? await getSessionUserClaimData(authClient) : null
};
}
})
}
}),
loader: async ({ context: { queryClient, queryOptions } }) => {
// We're using `fetchQuery` because `ensureQueryData` would ignore the
// staleTime and never refresh the query, while we want to periodically
// recheck the session so we can send the user to login if necessary.
const session = await queryClient.fetchQuery(queryOptions.session);

if (!session.isAuthenticated) {
// Redirect login here
}
}
});

function RouteComponent() {
const { queryOptions } = Route.useRouteContext();
const queryResult = useSuspenseQuery(queryOptions.session);

if (queryResult.data.isAuthenticated) {
return (
<SessionUserContext value={queryResult.data.sessionUser}>
<Outlet />
</SessionUserContext>
);
}

return null;
}
Be careful with ensureQueryData because that will always return stale data in the loader. If you want to periodically check your session to act on it if necessary (i.e. redirect) you'll have to use fetchQuery instead and combine it with a staleTime on the query as I do above. ensureQueryData ignores staleTime and just returns the most recent cached result, if I'm not mistaken.
other-emerald
other-emeraldOP•4mo ago
Ah that's good to know thanks 👀
other-emerald
other-emeraldOP•4mo ago
GitHub
RFC: Unified Imperative Query Methods · TanStack query · Discussi...
Context Sometimes, APIs don’t evolve well. I’ve seen the situation a couple of times that we add an API, and we think it’s great, and then after some time, we add another API that does something si...
optimistic-gold
optimistic-gold•4mo ago
Yeah, definitely! Will clear up things a lot… Also wasn't aware of the ensureQueryData({ invalidateIfStale: true }), could also be a solution for the issue above I suppose

Did you find this page helpful?