S
SolidJS8mo ago
dmayo2

parent of nested routes

Hello. Just looking for confirmation. I'm using Supabase Auth and that logic lives in RouteGuard. I'm pretty sure that all the routes nested within will be password protected. My main question is: am I configuring the Index component correctly? Will I be able to access it? If an unauthenticated user goes to '/' (or any of the nested routes) they will be navigate('/login'). I seem to be having an issue accessing '/' as an authenticated user. Should I rename the route for the Index component to someting like '/home'?
<Routes>
<Route path="/pricing" component={Pricing} />
<Route path="/login" component={Login} />
<Route path="/" component={RouteGuard}>
<Route path="/" component={Index} />
<Route path="/chat" component={Chat} />
<Route path="/billing" component={Billing} />
<Route path="/profile" component={Profile} />
<Route path="/settings" component={Settings} />
</Route>
<Route path="*" component={Sitemap} />
</Routes>
<Routes>
<Route path="/pricing" component={Pricing} />
<Route path="/login" component={Login} />
<Route path="/" component={RouteGuard}>
<Route path="/" component={Index} />
<Route path="/chat" component={Chat} />
<Route path="/billing" component={Billing} />
<Route path="/profile" component={Profile} />
<Route path="/settings" component={Settings} />
</Route>
<Route path="*" component={Sitemap} />
</Routes>
12 Replies
dmayo2
dmayo28mo ago
Just to clairfy: index.jsx snippet
<Router>
<App />
</Router>
<Router>
<App />
</Router>
app.jsx snippet:
<Routes>
<Route path="/pricing" component={Pricing} />
... see above for full snippet
</Routes>
<Routes>
<Route path="/pricing" component={Pricing} />
... see above for full snippet
</Routes>
RouteGuard.jsx snippet:
return (
<>
<Outlet />
</>
)
return (
<>
<Outlet />
</>
)
mdynnl
mdynnl8mo ago
you can pull it out of the nested route think of the wrapping Route as a means of grouping, it doesn't render on its own
dmayo2
dmayo28mo ago
Hi. But I want '/' to be protected. I guess I'll try to rename it to /home or /dashboard. My issue is that the supabase emailed login link is being hit once before the user hits it (micro seconds) so the link becomes invalid after one use. It was working fine before I nested routes. I had ternary logic for routes, but that wasn't working correctly, then I realized I could simplify the code with nested routes, but that has resulted in the double hit, so I can't log in.
mdynnl
mdynnl8mo ago
ah, i read it the other way. the configuration is correct
dmayo2
dmayo28mo ago
Thanks for the confirmation.
mdynnl
mdynnl8mo ago
where is email login handled and how? createResource + data func?
dmayo2
dmayo28mo ago
The login is a form in /login which is outside of RouteGuard. Supabase has a js client that you submit to. It checks the email against Auth.users. If it finds it, it responds with Ok, and sends an email with a link that contains a token that sets the session. The session logic is in RouteGuard:
import { Outlet, useNavigate } from "@solidjs/router";
import { createEffect, createSignal } from "solid-js";
import { supabase } from './components/supabaseClient'

export default function RouteGuard () {
const navigate = useNavigate();
const [session, setSession] = createSignal(null);

createEffect(() => {
// Fetch the session asynchronously
supabase.auth.getSession().then(({ data: { session } }) => {
setSession(session);
});
supabase.auth.onAuthStateChange((_event, session) => {
setSession(session);
});
if(!session()){
navigate('/login', { replace: true })
//console.log('in RG !session',session())
}
});

return (
<>
<Outlet />
</>
)
}
import { Outlet, useNavigate } from "@solidjs/router";
import { createEffect, createSignal } from "solid-js";
import { supabase } from './components/supabaseClient'

export default function RouteGuard () {
const navigate = useNavigate();
const [session, setSession] = createSignal(null);

createEffect(() => {
// Fetch the session asynchronously
supabase.auth.getSession().then(({ data: { session } }) => {
setSession(session);
});
supabase.auth.onAuthStateChange((_event, session) => {
setSession(session);
});
if(!session()){
navigate('/login', { replace: true })
//console.log('in RG !session',session())
}
});

return (
<>
<Outlet />
</>
)
}
The link from Supabase is redirected to / or I've also tried /profile which is inside RouteGuard (but so is /). This is the "magic login link" https://yrgprjcjvq.supabase.co/auth/v1/verify?token=abc1dc85df42f343608abac3295a67232&type=magiclink&redirect_to=http://localhost:3000 And the return is a hash to localhost:3000 This is the error: localhost:3000#error=unauthorized_client&error_code=401&error_description=Email+link+is+invalid+or+has+expired and a valid link with the token looks like: localhost:3000#access_token=eyJhbGciOiJIUzI1NiIsIPOk6yJV_adQssw5c&expires_in=3600&refresh_token=eyJhbGciOiJIUzI1NiIsInR5cC That link is only valid for 24 hours and is a one-time use. Somehow, that's getting hit simulatiously and thus when my code runs, it get's the expired link error. So, I'm trying to debug where it's getting hit twice.
dmayo2
dmayo28mo ago
No description
mdynnl
mdynnl8mo ago
not sure if it's related but onAuthStateChange should not be in that effect should be put into something like onMount or unsub with onCleanup
dmayo2
dmayo28mo ago
Thanks for the tip. No resolution though. I have onAuthStateChange in createEffect() as that is in all the examples I've found including supabase.com/docs
dmayo2
dmayo28mo ago
No description
mdynnl
mdynnl8mo ago
in this example, it's okay because there's no subscription to any signal