Waffleophagus
Waffleophagus2w ago

Logging into new user "doesn't work" on react native since I store state?

As mentioned in #"Upgrading" Anonymous accounts to "real" accounts with email I start all users out with an anonomyous account then letting them auth into a real account. I am trying to store some of that in a local store since its react native and my goal is to give an offline experience for my users, but the thing I've been banging my head against for the past like 3 evenings (yay off time projects) is that when a user auths with an email, it doesn't take effect immediately, and I end up having to exit and come back to the app, doing that solves it perfectly. Is it a race condition? What is the simplest way to handle this? I'll happily share anything I have to get this working.
14 Replies
Convex Bot
Convex Bot2w ago
Thanks for posting in <#1088161997662724167>. Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets. - Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.) - Use search.convex.dev to search Docs, Stack, and Discord all at once. - Additionally, you can post your questions in the Convex Community's <#1228095053885476985> channel to receive a response from AI. - Avoid tagging staff unless specifically instructed. Thank you!
erquhart
erquhart2w ago
Sounds like you got a bit further, nice! When you say "it doesn't take effect immediately", can you break that down some more
Waffleophagus
WaffleophagusOP2w ago
User goes through the OTP process, if they are logging into an existing account, it appears that nothing happens, they are kicked to the Home Screen and it looks like nothing changed. I logged the hell out of the flow and it also appears that it even refreshes the anonymous token? If you leave/kill the app and come back, the login takes effect. The worst case scenario is if you go in, add a bunch of data, then sign up, the migration we talked about DOES take effect immediately and all the data vanishes. It’s safely on the new account, but you have to leave/kill the app and come back to see it. I fully acknowledge this very well be a “skill issue” this is the first time I’ve messed with auth from this side of the isle (I’ve done the server jwt auth at previous jobs) I will happily share any code you wanna see on this, and honestly if we find a good solution I’ll happily open source it even, but I won’t be able to access the code till I’m home That said, yea, got the migration running super smoothly now, thanks again for the help on that part!
erquhart
erquhart2w ago
Is a new user record created, or is it just a new authAccount record linked to the existing user record?
Waffleophagus
WaffleophagusOP2w ago
New user record is the flow that the auth library does currently, hence the necessity of the migration A new user record (along with an authAccount) is created upon first hitting the first of the two OTP endpoints
erquhart
erquhart2w ago
You'd have to sign out and sign back in to seal the deal if a new user record is being created. I would just prompt to let them know the user creation was a success, and that they have to now log back in to move forward. Then log them out.
Waffleophagus
WaffleophagusOP2w ago
That’s a terrible flow Wouldn’t logging them out from their anon account when they hit the login button work? But if that’s the flow I gotta do for now I will.
erquhart
erquhart2w ago
That's worth trying I haven't tried any of what you're doing, but if the new account and user records are created when you send the otp, maybe logging out at that point will allow them to be logged back in when the enter the otp. I assumed they'd still need to be logged in when entering the otp.
Waffleophagus
WaffleophagusOP2w ago
Totally, I get that I may be trailblazing, I’d love to contribute back the solution if we find one. For what it’s worth, my plan is to have a TestFlight build with friends for a while, and if we don’t have a solution, to those folks I’ll just say “kill the app and reopen it and you’ll be golden” but before I ship, which my goal is “sometime this year” I’ll want a clean flow. I’m totally willing to help however I can to get there and share it. The anon “upgrade” flow is really powerful imo. Imma try the logout of anon account when you go to the login page, or maybe when you hit the “send email” button, and see if that works. If it doesn’t imma probably have to backburner this for a bit. I know that y’all are attempting to be a solid competitor to supabase, and they have a very clear path to do this thing, and convex’s DX is way better, so if I can help, totally willing
erquhart
erquhart2w ago
The right approach is to not create a new user account, I'd have to look and see what Convex Auth is doing there. Feel free to fork it and play around. I'm more likely to get this working in Better Auth than in Convex Auth at this point.
Waffleophagus
WaffleophagusOP2w ago
If I can get the rest of my app to a happy place I’ll happily fork and mess with it, but my priority at this point is the other stuff I still gotta do till my self imposed deadline at the end of next month to have a TestFlight build I’m happy with. I do think (hope?) the logout when you attempt to login behind the scenes may be the fix hopefully If I can give my TestFlight folks a functional app where they have a one off awkward onboarding, that’s fine. I... think... that worked!!!! 1. Anon on login 2. When they submit an email to sign up/login via OTP, make a pivot table that is just
authUpdateTable: defineTable({
userId: v.id("users"),
email: v.string(),
}),
authUpdateTable: defineTable({
userId: v.id("users"),
email: v.string(),
}),
3. log the anon user out 4. email sent 5. verify code 6. do the data migration 7. Success! I'll happily share the migration stuff if you like
erquhart
erquhart2w ago
Hey, glad it worked! Any code you can leave here might be helpful for someone else for sure.
Waffleophagus
WaffleophagusOP2w ago
Here's the pre-auth mapping for the migration:
export const preAuth = mutation({
args: {
email: v.string(),
},
handler: async (ctx, args) => {
const doesTheEmailExist = await ctx.db
.query("authUpdateTable")
.filter((q) => q.eq(q.field("email"), args.email))
.collect()
if (doesTheEmailExist.length > 0) {
return
}

const userId = await getAuthUserId(ctx)
ctx.db.insert("authUpdateTable", {
email: args.email,
userId: userId as Id<"users">,
})
},
})
export const preAuth = mutation({
args: {
email: v.string(),
},
handler: async (ctx, args) => {
const doesTheEmailExist = await ctx.db
.query("authUpdateTable")
.filter((q) => q.eq(q.field("email"), args.email))
.collect()
if (doesTheEmailExist.length > 0) {
return
}

const userId = await getAuthUserId(ctx)
ctx.db.insert("authUpdateTable", {
email: args.email,
userId: userId as Id<"users">,
})
},
})
Waffleophagus
WaffleophagusOP2w ago
And this is a text file for the migration code cause I guess it broke the character limit, hope it helps the next dev!

Did you find this page helpful?