Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(@realm/react) useEmailPasswordAuth.register should return a promise #6180

Closed
krollins-mdb opened this issue Oct 5, 2023 · 3 comments
Closed

Comments

@krollins-mdb
Copy link
Contributor

krollins-mdb commented Oct 5, 2023

Problem

For the useEmailPasswordAuth() hook, it would be great if register() returned a promise instead of void. The SDK's app.emailPasswordAuth.registerUser does that. Without returning a promise, it can be hard to work with a sequence of events, like linking identities.

For example:

const registerAndLinkIdentities = async () => {
    try {
	  // Could await old method.
      // await app.emailPasswordAuth.registerUser({email, password})
		
	  // Can't await `register`
      register({email, password});const credentials = Credentials.emailPassword(email, password);
	  // Which leads to "invalid username/password" here and aborts the
	  // still running registration process.
      await user.linkCredentials(credentials);} catch (error) {
      // Add error handling logic here
      console.error(error);
    }
};

Solution

useEmailPasswordAuth.register should return a promise that resolves based on app.emailPasswordAuth.registerUser's behavior.

Alternatives

No response

How important is this improvement for you?

I would like to have it but have a workaround

Feature would mainly be used with

Atlas App Services: Auth or Functions etc

@elle-j
Copy link
Contributor

elle-j commented Oct 6, 2023

For reacting to successful or failed login/registration, the idea is to use useEffect(). E.g.:

// Automatically logs the user in after successful registration.
useEffect(() => {
  if (result.operation === AuthOperationName.Register && result.success) {
    logIn({email, password});
  }
}, [/* ... */]);

The same pattern can be used with result.error. Although, I do agree that having the auth hooks (not only useEmailPassowrdAuth.register()) return a promise would be a nice DX improvement:

  • useEffect() can be avoided (along with "dependency array footguns" 🦶 🔫 ).
  • No need to wait for an additional rerender to perform whatever logic should come after.
  • Code becomes a bit more readable and traceable.
    • Also, the event-based action (e.g. registering after clicking "Register") can be grouped with related logic (e.g. linking identities as you showed).

Avoiding the need for try-catch:

For the calling code to avoid having to catch potential errors from a returned promise, we could have realm/react return the result or part of the result (thus, realm/react handles catching the error). Example usage:

const handleRegistration = () => {
  const { error } = await register(/* ... */);

  if (error) {
    // ...
  }
  
  // ...
};

Even if this was changed to return a promise, I don't believe we'd have to break existing behavior 👍

@takameyer
Copy link
Contributor

takameyer commented Oct 16, 2023

I've been giving this some thought, and I think the reason I shied away from making this a promise is that the result will not be updated in this case. The way functional hooks works, is the entire component is invoked on re-render, meaning the state updates would be not be applied in the then of the promise. If, however, you are awaiting a hook result, you won't be able to use the result to determine the success or failure of the operation.
If we were to make this a promise we would also have to throw an error on failure, which causes issues within hooks (the result state would never get updated to error and be stuck on pending).

In summary, if we made this a promise the then function would be called within a stale version of the component. I would therefore use the suggestion from @elle-j and keep the components the way they are.

I ended up finding out that there is a proposal for a promise hook from the React team. Here is an interesting blog post about that, which also details a bit of the issues one faces when using promises within react components.

@krollins-mdb
Copy link
Contributor Author

Thanks for clarifying, @takameyer! Totally makes sense. I'll close this issue. The proposal for a promise hook looks interesting!

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 14, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants