T
TanStack2y ago
xenial-black

How to handle auth context update

Hi guys i'm new to tanstack router and i'm loving it so far. I have a question though on the best way to handle authentication. At the moment my App component looks like this
const App = () => {
const { isPending, data: user } = useAuth();

if (isPending) {
//other stuff
}

//other stuff

return <RouterProvider router={router} context={{ queryClient, user }} />;
};
const App = () => {
const { isPending, data: user } = useAuth();

if (isPending) {
//other stuff
}

//other stuff

return <RouterProvider router={router} context={{ queryClient, user }} />;
};
and useAuth is just a hook that calls useQuery from tanstack query. I also have all my protected routes within this layout beforeload
export const Route = createFileRoute('/_protected')({
beforeLoad: ({ location, context: { user } }) => {
if (!user) {
throw redirect({
to: '/auth/login',
search: {
redirect: location.href,
},
});
}
},
});
export const Route = createFileRoute('/_protected')({
beforeLoad: ({ location, context: { user } }) => {
if (!user) {
throw redirect({
to: '/auth/login',
search: {
redirect: location.href,
},
});
}
},
});
so if the user is not logged it will be redirected to login page with that search parameter. One the user submits the login form, this function is called
const submitForm: SubmitHandler<UserLogin> = async (data) => {
try {
await signin(data);
} catch (error) {
//other stuff
}
//other stuff

await queryClient.invalidateQueries(authQueryOptions);
navigate({ to: redirect ?? '/', replace: true });
};
const submitForm: SubmitHandler<UserLogin> = async (data) => {
try {
await signin(data);
} catch (error) {
//other stuff
}
//other stuff

await queryClient.invalidateQueries(authQueryOptions);
navigate({ to: redirect ?? '/', replace: true });
};
the issue i'm having is that when redirect is not null or undefined, and is within a protected route, the above layout's beforeload will be called before the ui is updated with the new auth state, forcing the user to click the login button twice. Is there a way to avoid such a thing?
1 Reply
xenial-black
xenial-blackOP2y ago
export const Route = createFileRoute('/_protected')({
beforeLoad: ({ location, context: { queryClient } }) => {
const user = queryClient.getQueryData(authQueryOptions.queryKey);
if (!user) {
throw redirect({
to: '/auth/login',
search: {
redirect: location.href,
},
});
}
},
});
export const Route = createFileRoute('/_protected')({
beforeLoad: ({ location, context: { queryClient } }) => {
const user = queryClient.getQueryData(authQueryOptions.queryKey);
if (!user) {
throw redirect({
to: '/auth/login',
search: {
redirect: location.href,
},
});
}
},
});
I think i found a solution, since i await for the auth query to be invalidated, it means that data will be updated, so instead of checking that's in the context i just get the updated one from the queryclient

Did you find this page helpful?