Exception thrown when invoking useNavigate within Router root layout
I am having a real hard time working through this problem. I feel like I've tried everything but nothing has been working and there's probably something I'm not seeing clearly anymore.
The short of it is, when I attempt to invoke
navigate("/login")
from my root layout component, I am greeted with the following exception:
Here is the entirety of my App.tsx
file:
The area to focus on is the onClick
for the Sign Out NavbarLink
. In the callback, I am invoking the Better Auth client to sign out and on success, I navigate to /login
. It's that invocation that causes the exception.
I'm not exactly sure the proper way to debug this and could use all the help I can get19 Replies
Just adding more additional context here. The
NavbarLink
components are just <A>
elements from @solidjs/router
wrapped under <li>
tags.
And for reference, here is my Login.tsx
:
I make heavy use of the getAuthState
query which you can see here:
From the looks of it, I do see the url change in my app showing that it went to /login
-- however, everytime it does, the <ErrorBoundary>
fallback component kicks in and displays instead of the Login page I defined above due to that thrown exception.Maybe moving the RootLayout to a different file and importing in app.tsx helps?
To me this
has an uncanny similarity to your previous issue
https://discord.com/channels/722131463138705510/1331326621629812766
so why not give something like
a try.
Having at the look at the documentation
https://www.better-auth.com/docs/basic-usage#signout
Note the
await
.
So it should have really been
all along.Basic Usage | Better Auth
Getting started with Better Auth
@peerreynders unfortunately the refactoring to async/await syntax results in the same TypeError exception
Shifting the
RootLayout
into its own module also had no impact unfortunately
@peerreynders also, I get complaints from the Solid ESLint rules around async callbacks:
That's why I went with the object callback structure from the Better Auth docs around signOut
Sure. The message
would lead me to the hypothesis that perhaps somehow the
navigate
doesn't seem to have access to the router when it is executed.
Frankly at this point does even:
work?
As a sanity check, this (as expected) works:
@peerreynders I think I may have an idea of what is causing the problem which leads me to a question -- I am using
query
to cache data regarding my session state. After signing out using Better Auth, I need to revalidate that cache key which my components depend on for session state. Can I use revalidate
outside of a query
?You should be able to as long as you pass it the correct key.
https://github.com/solidjs/solid-router/blob/50c5d7bdef6acc5910c6eb35ba6a24b15aae3ef6/src/data/query.ts#L41-L49
revalidate
just accesses the module global cacheMap
.GitHub
solid-router/src/data/query.ts at 50c5d7bdef6acc5910c6eb35ba6a24b15...
A universal router for Solid inspired by Ember and React Router - solidjs/solid-router
I was away from my computer which was why I asked the above question. Just rushed back to try it out and that did the trick for a simple use-case (I removed my authenticated route protection) but then that finally revealed what I believe is the true cause of my issue
Ugh...nvm, I spoke too soon ðŸ˜
I thought the problem had to do with my SignIn component here:
But I think the issue is some combination of the
navigate
calls here and what I am doing to implement "protected" routes in my app here with the Router:
My ActiveUserSession
component is here:
What I see is that the navigate post sign out does occur and my URL reflects the login
redirect but that is where I hit the error boundary fallback view. I was thinking that some navigate
was occurring to a protected route that was no longer mounted since the user session is over but none of the console logs I place get triggered and I don't see a navigate called anywhere else post the login redirect...side thought: could you eliminate
ActiveUserSession
if in
getAuthState()
just throw redirect('/login')
when there is no authentication?You referring to the actual implementation here?
Yes, either return a user record OR throw a redirect to
/login
.
In the case of strello it doesn't seem to interfere with the /login
routeGitHub
strello/src/lib/index.ts at 9c9ae973d96cc045914e696757a1b5f31efc6fa...
Contribute to solidjs-community/strello development by creating an account on GitHub.
Just did the following and still the same result -- also removed the
navigate("/login")
on the success handler for signOut and just relying on revalidate(getAuthState.key)
to trigger that new throw
in the query
ðŸ˜
So the error isn't related to the
navigate()
? Something else that happens during the logout process? Is the login route running into trouble after logout?I'm suspecting it must be related to routing/navigating in some way since the exception is about
path
but I could be off the mark
Yes, the app routes to login but then displays the error boundary fallback once it arrives
This thing just gets weirder and weirder -- how about this for a brain-buster moment. So, I managed to get my app to successfully sign out without causing the exception and you're going to love the steps I just did...
1. Authenticate from Login and get redirected to /dashboard
2. On /dashboard
manually update url path in browser URL bar to /login
to have Login component redirect me back to /dashboard
3. Sign out from /dashboard
and get redirected back to /login
without crashing 🤯
I do not know what breadcrumbs we can gleam from the above workflow...Another random aside:
Route
components support a preload
prop
https://docs.solidjs.com/solid-router/reference/preload-functions/preload
Given that you should be able to mimic strello
https://github.com/solidjs-community/strello/blob/9c9ae973d96cc045914e696757a1b5f31efc6fa1/src/lib/index.ts#L41-L49
https://github.com/solidjs-community/strello/blob/9c9ae973d96cc045914e696757a1b5f31efc6fa1/src/routes/login.tsx#L11
to navigate to /dashboard
and eliminate another dependency to useNavigate
(and running it inside an effect).
Is it going to solve your current problem? No?GitHub
strello/src/lib/index.ts at 9c9ae973d96cc045914e696757a1b5f31efc6fa...
Contribute to solidjs-community/strello development by creating an account on GitHub.
GitHub
strello/src/routes/login.tsx at 9c9ae973d96cc045914e696757a1b5f31ef...
Contribute to solidjs-community/strello development by creating an account on GitHub.
I think I finally found the problem!! It appears that
ActiveUserSession
was the problem all along...
I went from this:
To this and everything works correctly:
I'm suspecting that the authState
guard for redirecting was probably being overloaded in some way? Like I have that authState
used in the RootLayout
which contains that redirect
we added to the underlying query
and that should be sufficient in redirecting to Login across all the protected pages
But I'm not sure about that whole explanation. I would like to really know what was going on there. It was really hard to parse the error and really pinpoint what the crux of the issue wasand that should be sufficient in redirecting to Login across all the protected pagesYour "Not Found" component would only work for authenticated users. Also if you implement
logout
as an action
async isn't an issue and you can just throw redirect("/login")
at the end.
https://docs.solidjs.com/solid-router/reference/data-apis/use-action
Consider making signin an action for the same reason. (Looks like you already did)I think I can be fine with that. Basically if someone is not logged in and trying to manually navigate anywhere else, I want that to take them back to login. But excellent observation there. I did not realize that until you brought it up 😃
This is my first time trying to use SolidJS for an app I hope to productionize so all of our dialogue and your input like this has been incredibly helpful! Can't thank you enough for your time and patience @peerreynders :appwriteheart: