Authentication Context Updates vs Redirect (Race Condition) & Maybe useRouteContext() is Static?!
Hey all! New to Tanstack Router here, and trying to follow the Authentication guide (https://tanstack.com/router/latest/docs/framework/react/guide/authenticated-routes) and Authenticated Routes Context example (https://tanstack.com/router/latest/docs/framework/react/examples/authenticated-routes-context) but I'm running into a situation where, upon login/logout, my redirects (to Dashboard on login and Login on logout) beat the context update –if it is indeed actually updating– and the wrong info is rendered.
My suspicion is that this is because the router's context isn't actually updating at all when it's supposed to?! That feels like I'm doing something wrong.
In debugging this, I've been able to see that when my
useAuth() context hook updates and its new state gets passed into the <RouterProvider /> context, a page component that calls useRouteContext() like the following never receives that new state:
const { isLoading } = myRoute.useRouteContext({ select: ({ auth }) => ({ isLoading: auth.isLoading }) });
My page just shows its loading state forever.
Similarly, it doesn't appear that the router ever learns that the user has changed within the auth state (to a user object or to null), which could explain why I see the wrong info in my intro paragraph above.
I've attached some pared down code in comments below for diagnosis! Thanks so much for your help.Authenticated Routes | TanStack Router Docs
Authentication is an extremely common requirement for web applications. In this guide, we'll walk through how to use TanStack Router to build protected routes, and how to redirect users to login if they try to access them.
The route.beforeLoad Option
React Router Authenticated Routes Context Example | TanStack Router...
An example showing how to implement Authenticated Routes Context in React Router
11 Replies
fascinating-indigo•2y ago
I have the same issue there: #Context & protected routes
stormy-goldOP•2y ago
First, my Auth Context
Second: Routes, Router, and Context Provider Setup
I've segmented my routes under two parents, one for the routes that you must be logged out to see (like /login), the other for routes that you must be logged in to access (in this demo, /home).
fascinating-indigo•2y ago
In fact, the context is setted by default to default...
then, it updates
but this is a big issue for authenticated routes
stormy-goldOP•2y ago
Finally, attempting to utilize my auth context in a rendered component
💻 The Result
Initially, the console prints:
Then the Auth Provider's useEffect() runs to fetch the user (still signed out, still null) from the API, and the console prints:
And the browser just shows "Loading...", because even though
useAuth() knows isLoading is false, and its result is passed into <RouterProvider />'s context, isLoading never becomes false in useRouteContext() 😢
Oh! I almost forgot! The above is one blocking issue, but it's not the race condition I'm experiencing, it's just in the way!
I have a sneaking suspicion that if I can get the root layout to show a loading state whenever the user changes from signed out to signed in and vice versa, this race condition might just go away. But I also suspect that if I can solve the fact that this useRouteContext() isn't updating, the components that need user from it will just work instead of being broken until a file change or browser refresh cause a rerender
@Sean Cassiere I saw you were helping @wailroth earlier with their recent post about something potentially similar – does having a second example help hone in on what might be going on here?
Popping back in to say that if I switch all my useRouteContext()s for useAuth()s, taking the state from my AuthProvider directly instead of through the RouterProvider (which again, is being fed that exact same state), everything works perfectly!fascinating-indigo•2y ago
I think I should do the same so
where are you calling it?
because thing like should not work, useAuth is a react hook
stormy-goldOP•2y ago
Ah, no I'm not doing mine in createFileRoute(), I actually found that my authenticated and unauthenticated route parents seem to get
context.auth.isAuthenticated just fine... which is even more strange
I'm calling useAuth() in the components the route mounts. In my code samples above, that means my third/final code block right before the console logs part – I replaced const { isLoading } = rootRoute.useRouteContext({... with const { isLoading } = useAuth() to skip over the router context and go straight to the auth context for that datafascinating-indigo•2y ago
have you an example of that ?
i'm not sure i'm well understanding
stormy-goldOP•2y ago
Now, this root component will show a loading message until my Auth Provider is done fetching the user from the API in its useEffect(), that result goes into the Auth Provider's context, and useAuth() has access to it here 🙂
fascinating-indigo•2y ago
because the major issue I have is to protect my routes;
when I redirect an user from a link, there is not issues.
But when I access to a route manually, like in #Context & protected routes , the context is not the same
so i'm a little bit annoyed by that
stormy-goldOP•2y ago
Interesting, I don't know if you saw above but I have an
authenticatedRoute created that doesn't have a path, but it does check for signed-in status and redirect if it doesn't find it. Then any page I want to have use that behavior, I set getParentRoute: () => authenticatedRoute
And in that authenticatedRoute, for whatever reason, context.auth.isAuthenticated appears to be reliablefascinating-indigo•2y ago
okay; I should do it like you
I think
How do you implement this
authenticatedRoute ?
with this:
?
Btw i'm using fileBased routes
when you follow this: https://codesandbox.io/p/devbox/github/tanstack/router/tree/main/examples/react/authenticated-routes-context?embed=1&file=%2Fsrc%2Fmain.tsx&theme=dark
you see that they are doing it like me