Skip to main content

useForgotPassword

Implementing a secure password recovery flow requires orchestrating multiple steps correctly. The useForgotPassword hook simplifies this complexity by providing the foundational methods needed to request OTP codes, verify user identities securely, and ultimately reset their passwords.

Return Value

loading
boolean
Whether a password reset operation is in progress
forgotPassword
(email: string) => Promise<ActionResult>
verifyOtp
(email: string, otp: string) => Promise<ActionResult>
resetPassword
(token: string, newPassword: string) => Promise<ActionResult>
import { useForgotPassword } from "@wacht/tanstack-router";

function ForgotPasswordPage() {
  const { loading, forgotPassword, verifyOtp, resetPassword } = useForgotPassword();

  const [step, setStep] = useState<"email" | "otp" | "done">("email");
  const [email, setEmail] = useState("");
  const [token, setToken] = useState("");

  const handleSendCode = async () => {
    const result = await forgotPassword(email);
    if (result.data) {
      setStep("otp");
    }
  };

  const handleVerifyOtp = async (otp: string) => {
    const result = await verifyOtp(email, otp);
    if (result.data?.token) {
      setToken(result.data.token);
      setStep("done");
    }
  };

  const handleReset = async (newPassword: string) => {
    const result = await resetPassword(token, newPassword);
    if (result.data) {
      setStep("done");
    }
  };

  return (
    <div>
      {step === "email" && (
        <form onSubmit={() => handleSendCode()}>
          <input
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            placeholder="Enter your email"
          />
          <button disabled={loading}>Send Reset Code</button>
        </form>
      )}
      {step === "otp" && (
        <form onSubmit={(e) => {
          e.preventDefault();
          handleVerifyOtp("123456");
        }}>
          <input placeholder="Enter OTP code" />
          <button disabled={loading}>Verify</button>
        </form>
      )}
      {step === "done" && <p>Password reset successfully!</p>}
    </div>
  );
}

Examples

Initiate Password Reset

const { forgotPassword } = useForgotPassword();

const result = await forgotPassword("user@example.com");

// Returns success if OTP was sent
// result.data?: {}
// result.error?: ErrorInterface

Verify OTP

const { verifyOtp } = useForgotPassword();

const result = await verifyOtp("user@example.com", "123456");

// result.data?: { token: string }
// result.error?: ErrorInterface

Reset Password

const { resetPassword } = useForgotPassword();

const result = await resetPassword("token_from_otp", "NewSecurePassword123!");

// result.data?: Session
// result.error?: ErrorInterface

The Complete Password Reset Lifecycle

A secure password recovery operation follows a strict, multi-step sequence:
  1. Initiation: The user provides their registered email address.
  2. Dispatch: You invoke forgotPassword(email) to trigger a secure OTP dispatch to that address.
  3. Challenge: The user receives and inputs the OTP code into your interface.
  4. Verification: You invoke verifyOtp(email, otp) to cryptographically verify the code, receiving a temporary reset token.
  5. Resolution: The user provides a new, strong password.
  6. Completion: You invoke resetPassword(token, newPassword) to securely finalize the reset and establish a new session.