SignIn from email link, useUser() return leads to redirect bug
When I click the signin/signup link in email and get redirected to the app, I miss the page I made to welcome new users and gather more info for their profile because there's a moment where useUser() says it's no longer loading, but it doesn't provide a user object to my page.
In this demo all users will land on the welcome page regardless of whether or not they are new. I added http://localhost:3000/welcome as an Additional Redirect URL in Supabase and I pass { redirectTo: 'http://localhost:3000/welcome' } to supabaseClient.auth.signIn() which seems to have worked out, even for magic emails.
I've created a barebones pages/welcome.tsx file just to see what the values / steps are for useUser():
function WelcomePage() {
const { isLoading, user, userDetails } = useUser();
supabaseClient.auth.onAuthStateChange((event, session) => {
console.log(event, session);
});
console.log(isLoading, user, userDetails);
useEffect(() => {
if (!isLoading && !user)
router.replace('/signin');
}, [isLoading, user]);
if (isLoading) {
return (
<span>Loading...</span>
);
}
if (user) {
return (
<span>{ user.email }</span>
);
}
return (
<span>Redirecting...</span>
);
}
And here's what prints to the console:
true null undefined
[Fast Refresh] rebuilding
false null undefined
SIGNED_IN {...object with access_token, user, etc...}
SIGNED_IN {...object with access_token, user, etc...}
true null undefined
// The SIGNED_IN/object about four more times
true null undefined
true {...object with id, aud, email, etc...} undefined
false {...object with id, aud, email, etc...} undefined
So as you can imagine, that one instant where it stops loading but user is still null pushes me back to /signin. But onAuthStateChange() knew there was a valid user even before useUser() returned null two more times!
My pages/signin.tsx has a similar check for user, where if it finds one it calls router.replace('/') to send the user back to the homepage. This whole process flickers by in an instant and a new user would miss my welcome page entirely.
It appears as though that false null print happens exactly when #access_token=... is removed from the URL (I screen recorded so I could move frame-by-frame through the redirects).
Returning to /welcome and refreshing prints the following to the console:
true null undefined
[Fast Refresh] rebuilding
true null undefined
true {...object with id, aud, email, etc...} undefined
false {...object with id, aud, email, etc...} undefined
With no redirect to /signin, so it's definitely just when arriving fresh from the email link. However, it's probably notable that the user object has null for confirmed_at and created_at or any other date values, and userDetails remains undefined the whole time in both page load scenarios.
As a temporary fix, I've started storing the session from onAuthStateChange() with useState(), watching that from the useEffect() and including it in the list of "and not"s before pushing the user to /signin but that feels like it should be unnecessary!