Skip to main content

methods/email-password/react

React client for the emailPassword method, exported at @convex-dev/auth/methods/email-password/react.

Type Aliases​

CompleteChangeEmailState​

type CompleteChangeEmailState = LinkFlowState<
| ExtractError<CompleteChangeEmailResult>
| MissingSecretError
| OtherError>;

The state of useCompleteChangeEmail.


CompletePasswordRecoveryResult​

type CompletePasswordRecoveryResult =
| ClientView<CompletePasswordRecoveryResult>
| SignInUnexpectedFailure;

The result of the completePasswordRecovery callback of the ready state of useCompletePasswordRecovery.


CompletePasswordRecoveryState​

type CompletePasswordRecoveryState =
| {
status: "loading";
}
| {
completePasswordRecovery: (args) => Promise<CompletePasswordRecoveryResult>;
pending: boolean;
status: "ready";
}
| {
status: "complete";
}
| {
status: "error";
userError: PasswordRecoveryLinkError | MissingSecretError;
};

The state of useCompletePasswordRecovery. Unlike the other landing page hooks, the flow needs input from the user (the new password) before it can complete, so a ready state carries the function to submit it.

Union Members​

Type Literal​
{
status: "loading";
}

Type Literal​
{
completePasswordRecovery: (args) => Promise<CompletePasswordRecoveryResult>;
pending: boolean;
status: "ready";
}
completePasswordRecovery​
completePasswordRecovery: (args) => Promise<CompletePasswordRecoveryResult>;

Set the new password and sign the user in. Errors about the new password come back in the result and leave the state ready, so the user can try another password with the same link.

Parameters​
ParameterType
args{ newPassword: string; }
args.newPasswordstring
Returns​

Promise<CompletePasswordRecoveryResult>

pending​
pending: boolean;

true while completePasswordRecovery is in flight.

status​
status: "ready";

Type Literal​
{
status: "complete";
}

Type Literal​
{
status: "error";
userError: PasswordRecoveryLinkError | MissingSecretError;
}

CompleteSignUpState​

type CompleteSignUpState = LinkFlowState<
| SignInError<ClientView<CompleteSignUpResult>>
| MissingSecretError
| OtherError>;

The state of useCompleteSignUpWithEmailPassword.


LinkFlowState​

type LinkFlowState<UserError> =
| {
status: "loading";
}
| {
status: "complete";
}
| {
status: "error";
userError: UserError;
};

The state of a landing page hook: loading until the link has been presented, then complete or error.

Type Parameters​

Type Parameter
UserError

PasswordRecoveryApi​

type PasswordRecoveryApi = object;

The functions that useCompletePasswordRecovery calls. The app's api.auth has both of them.

Properties​

PropertyType
checkPasswordRecoveryCheckPasswordRecoveryQuery
completePasswordRecoveryCompletePasswordRecoveryMutation

SignInResult​

type SignInResult =
| ClientView<SignInResult>
| SignInUnexpectedFailure;

The result of the signIn callback from useSignInWithEmailPassword.


SignUpResult​

type SignUpResult =
| WithoutSecret<ClientView<SignUpResult>>
| UnexpectedFailure;

The result of the signUp callback from useSignUpWithEmailPassword.


StartChangeEmailResult​

type StartChangeEmailResult =
| WithoutSecret<StartChangeEmailResult>
| UnexpectedFailure;

The result of the startChangeEmail callback from useStartChangeEmail.


StartPasswordRecoveryResult​

type StartPasswordRecoveryResult =
| WithoutSecret<StartPasswordRecoveryResult>
| UnexpectedFailure;

The result of the startPasswordRecovery callback from useStartPasswordRecovery.

Functions​

useCompleteChangeEmail()​

function useCompleteChangeEmail(api, emailCode): CompleteChangeEmailState;

Client for the landing page of the email-change confirmation link: as soon as the page opens, present the code from the link with the secret stored by useStartChangeEmail. No session is adopted: the user already has one, and the backend requires it.

Parameters​

ParameterTypeDescription
api{ completeChangeEmail: CompleteChangeEmailMutation; }The functions of the method, usually api.auth.
api.completeChangeEmailCompleteChangeEmailMutation-
emailCode{ emailCode: string; }The code query parameter of the link.
emailCode.emailCodestring-

Returns​

CompleteChangeEmailState


useCompletePasswordRecovery()​

function useCompletePasswordRecovery(recoveryApi, emailCode): CompletePasswordRecoveryState;

Client for the landing page of the password-reset link. As soon as the page opens, it reads the secret stored by useStartPasswordRecovery and subscribes to checkPasswordRecovery with it and the code from the link. When the link can be used, the state is ready, with the function that sets the new password and adopts the minted session. When the link cannot be used, the state is error, so the page does not ask for a password.

The check is a subscription, thus the state moves to error on its own when the link dies while the page is open: another tab claims it, or it expires and the server erases it.

The hook does not complete the flow by itself: the flow needs the new password, so call completePasswordRecovery when the user submits the form. An error about the password keeps the state ready, so show it in the form. An error about the link moves the state to error.

function ResetPassword({ emailCode }: { emailCode: string }) {
const state = useCompletePasswordRecovery(api.auth, { emailCode });
const [newPassword, setNewPassword] = useState("");
const [error, setError] = useState<string | null>(null);

switch (state.status) {
case "loading":
return <p>Checking the link…</p>;
case "complete":
return <Navigate to="/" replace />;
case "error":
// map state.userError (MISSING_SECRET, INVALID_CHALLENGE, …) to a message
return <p role="alert">This link cannot be used.</p>;
}

return (
<form
onSubmit={async (e) => {
e.preventDefault();
const result = await state.completePasswordRecovery({ newPassword });
// map result.userError (PASSWORD_TOO_SHORT, …) to a message
setError(result.status === "error" ? result.userError.error : null);
}}
>
<label>
New password
<input
type="password"
autoComplete="new-password"
required
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
disabled={state.pending}
/>
</label>
{error !== null && <p role="alert">{error}</p>}
<button type="submit" disabled={state.pending}>
Reset password and sign in
</button>
</form>
);
}

Parameters​

ParameterTypeDescription
recoveryApiPasswordRecoveryApiThe app's checkPasswordRecovery query and completePasswordRecovery mutation references, for example api.auth.
emailCode{ emailCode: string; }The code query parameter of the link.
emailCode.emailCodestring-

Returns​

CompletePasswordRecoveryState


useCompleteSignUpWithEmailPassword()​

function useCompleteSignUpWithEmailPassword(api, emailCode): CompleteSignUpState;

Client for the landing page of the validation link: as soon as the page opens, present the code from the link with the secret stored by useSignUpWithEmailPassword, and adopt the minted session.

function ValidateEmail({ emailCode }: { emailCode: string }) {
const state = useCompleteSignUpWithEmailPassword(api.auth, { emailCode });
switch (state.status) {
case "loading": // validating…
case "complete": // signed in
case "error": // map state.userError to a message
}
}

Parameters​

ParameterTypeDescription
api{ completeSignUpWithEmailPassword: CompleteSignUpMutation; }The functions of the method, usually api.auth.
api.completeSignUpWithEmailPasswordCompleteSignUpMutation-
emailCode{ emailCode: string; }The code query parameter of the link.
emailCode.emailCodestring-

Returns​

CompleteSignUpState


useSignInWithEmailPassword()​

function useSignInWithEmailPassword(api): object;

Client for the sign-in flow: run the signInWithEmailPassword mutation and, on success, establish an authenticated session.

function LogIn() {
const { signIn, pending } = useSignInWithEmailPassword(api.auth);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState<string | null>(null);

return (
<form
onSubmit={async (e) => {
e.preventDefault();
const result = await signIn({ email, password });
// map result.userError (INVALID_CREDENTIALS, …) to a message
setError(result.status === "error" ? result.userError.error : null);
}}
>
<label>
Email
<input
type="email"
autoComplete="username"
required
value={email}
onChange={(e) => setEmail(e.target.value)}
disabled={pending}
/>
</label>
<label>
Password
<input
type="password"
autoComplete="current-password"
required
value={password}
onChange={(e) => setPassword(e.target.value)}
disabled={pending}
/>
</label>
{error !== null && <p role="alert">{error}</p>}
<button type="submit" disabled={pending}>
Log in
</button>
</form>
);
}

Parameters​

ParameterTypeDescription
api{ signInWithEmailPassword: SignInMutation; }The functions of the method, usually api.auth.
api.signInWithEmailPasswordSignInMutation-

Returns​

object

pending​
pending: boolean;
signIn​
signIn: (credentials) => Promise<SignInResult>;
Parameters​
ParameterType
credentials{ email: string; password: string; }
credentials.emailstring
credentials.passwordstring
Returns​

Promise<SignInResult>


useSignUpWithEmailPassword()​

function useSignUpWithEmailPassword(api): object;

Client for the sign-up flow: run the signUpWithEmailPassword mutation and keep the returned secret for useCompleteSignUpWithEmailPassword.

A successful sign-up does not sign the user in: it sends the validation email. Tell the user to open the link (in this same browser).

function SignUp() {
const { signUp, pending } = useSignUpWithEmailPassword(api.auth);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState<string | null>(null);
const [sentTo, setSentTo] = useState<string | null>(null);

if (sentTo !== null) {
return <p>We sent a link to {sentTo}. Open it in this browser.</p>;
}

return (
<form
onSubmit={async (e) => {
e.preventDefault();
const result = await signUp({ email, password });
if (result.success) {
setSentTo(email);
} else {
// map result.userError (EMAIL_TAKEN, PASSWORD_TOO_SHORT, …) to a message
setError(result.userError.error);
}
}}
>
<label>
Email
<input
type="email"
autoComplete="username"
required
value={email}
onChange={(e) => setEmail(e.target.value)}
disabled={pending}
/>
</label>
<label>
Password
<input
type="password"
autoComplete="new-password"
required
value={password}
onChange={(e) => setPassword(e.target.value)}
disabled={pending}
/>
</label>
{error !== null && <p role="alert">{error}</p>}
<button type="submit" disabled={pending}>
Create account
</button>
</form>
);
}

Parameters​

ParameterTypeDescription
api{ signUpWithEmailPassword: SignUpMutation; }The functions of the method, usually api.auth.
api.signUpWithEmailPasswordSignUpMutation-

Returns​

object

pending​
pending: boolean;
signUp​
signUp: (credentials) => Promise<SignUpResult>;
Parameters​
ParameterType
credentials{ email: string; password: string; }
credentials.emailstring
credentials.passwordstring
Returns​

Promise<SignUpResult>


useStartChangeEmail()​

function useStartChangeEmail(api): object;

Client for starting an email change: run the backend's startChangeEmail mutation and keep the returned secret for useCompleteChangeEmail.

Parameters​

ParameterTypeDescription
api{ startChangeEmail: StartChangeEmailMutation; }The functions of the method, usually api.auth.
api.startChangeEmailStartChangeEmailMutation-

Returns​

object

pending​
pending: boolean;
startChangeEmail​
startChangeEmail: (args) => Promise<StartChangeEmailResult>;
Parameters​
ParameterType
args{ currentPassword: string; newEmail: string; }
args.currentPasswordstring
args.newEmailstring
Returns​

Promise<StartChangeEmailResult>


useStartPasswordRecovery()​

function useStartPasswordRecovery(api): object;

Client for starting a password recovery: run the backend's startPasswordRecovery mutation and keep the returned secret for useCompletePasswordRecovery. On success, sentTo gives the address that received the link. Show this address to the user, not the typed one: the two can differ in case or in Unicode form.

Parameters​

ParameterTypeDescription
api{ startPasswordRecovery: StartPasswordRecoveryMutation; }The functions of the method, usually api.auth.
api.startPasswordRecoveryStartPasswordRecoveryMutation-

Returns​

object

pending​
pending: boolean;
startPasswordRecovery​
startPasswordRecovery: (args) => Promise<StartPasswordRecoveryResult>;
Parameters​
ParameterType
args{ email: string; }
args.emailstring
Returns​

Promise<StartPasswordRecoveryResult>