The useForgotPassword and useResetPassword hooks provide functionality for password reset flows including sending reset emails and setting new passwords.

Import

import { useForgotPassword, useResetPassword } from '@snipextt/wacht';

Hooks Overview

useForgotPassword

Initiates a password reset by sending a verification email.
import { useForgotPassword } from '@snipextt/wacht';

function ForgotPasswordForm() {
  const { forgotPassword, loading, error } = useForgotPassword();

  const handleSubmit = async (email) => {
    const result = await forgotPassword(email);
    
    if (!result.errors) {
      console.log('Reset email sent successfully');
    }
  };

  return (
    <form onSubmit={(e) => {
      e.preventDefault();
      const email = e.target.email.value;
      handleSubmit(email);
    }}>
      <input 
        name="email" 
        type="email" 
        placeholder="Enter your email"
        required 
      />
      <button type="submit" disabled={loading}>
        {loading ? 'Sending...' : 'Send Reset Email'}
      </button>
      {error && <p className="error">{error.message}</p>}
    </form>
  );
}

useResetPassword

Completes the password reset with verification code and new password.
import { useResetPassword } from '@snipextt/wacht';

function ResetPasswordForm({ email }) {
  const { resetPassword, loading, error } = useResetPassword();

  const handleReset = async (otp, newPassword) => {
    const result = await resetPassword(email, otp, newPassword);
    
    if (!result.errors) {
      console.log('Password reset successful');
      // Redirect to sign in
    }
  };

  return (
    <form onSubmit={(e) => {
      e.preventDefault();
      const formData = new FormData(e.target);
      handleReset(
        formData.get('otp'),
        formData.get('password')
      );
    }}>
      <input 
        name="otp" 
        type="text" 
        placeholder="Enter 6-digit code"
        maxLength="6"
        required 
      />
      <input 
        name="password" 
        type="password" 
        placeholder="New password"
        required 
      />
      <button type="submit" disabled={loading}>
        {loading ? 'Resetting...' : 'Reset Password'}
      </button>
      {error && <p className="error">{error.message}</p>}
    </form>
  );
}

Properties

useForgotPassword

loading
boolean
Whether the forgot password request is in progress
error
Error | null
Any error that occurred during the request

useResetPassword

loading
boolean
Whether the password reset is in progress
error
Error | null
Any error that occurred during the reset

Methods

forgotPassword()

Sends a password reset email to the specified address.
email
string
required
The email address to send the reset link to
const { forgotPassword } = useForgotPassword();

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

resetPassword()

Resets the password using the verification code.
email
string
required
The email address associated with the reset
otp
string
required
The 6-digit verification code from the email
password
string
required
The new password to set
const { resetPassword } = useResetPassword();

const result = await resetPassword(
  'user@example.com',
  '123456',
  'newSecurePassword123'
);

Examples

Complete Password Reset Flow

function PasswordResetFlow() {
  const [step, setStep] = useState('forgot');
  const [email, setEmail] = useState('');
  
  const { forgotPassword, loading: forgotLoading } = useForgotPassword();
  const { resetPassword, loading: resetLoading } = useResetPassword();

  const handleForgotPassword = async (e) => {
    e.preventDefault();
    const result = await forgotPassword(email);
    
    if (!result.errors) {
      setStep('reset');
    }
  };

  const handleResetPassword = async (e) => {
    e.preventDefault();
    const formData = new FormData(e.target);
    
    const result = await resetPassword(
      email,
      formData.get('otp'),
      formData.get('password')
    );
    
    if (!result.errors) {
      setStep('success');
    }
  };

  if (step === 'reset') {
    return (
      <div>
        <h2>Check Your Email</h2>
        <p>We sent a verification code to {email}</p>
        <form onSubmit={handleResetPassword}>
          <input 
            name="otp" 
            type="text" 
            placeholder="Enter 6-digit code"
            maxLength="6"
            pattern="[0-9]{6}"
            required 
          />
          <input 
            name="password" 
            type="password" 
            placeholder="New password"
            minLength="8"
            required 
          />
          <input 
            name="confirmPassword" 
            type="password" 
            placeholder="Confirm password"
            required 
          />
          <button type="submit" disabled={resetLoading}>
            {resetLoading ? 'Resetting...' : 'Reset Password'}
          </button>
        </form>
        <button onClick={() => setStep('forgot')}>
          Didn't receive code? Try again
        </button>
      </div>
    );
  }

  if (step === 'success') {
    return (
      <div>
        <h2>Password Reset Successful</h2>
        <p>Your password has been reset successfully.</p>
        <a href="/signin">Sign In</a>
      </div>
    );
  }

  return (
    <div>
      <h2>Forgot Password</h2>
      <form onSubmit={handleForgotPassword}>
        <input 
          type="email" 
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          placeholder="Enter your email"
          required 
        />
        <button type="submit" disabled={forgotLoading}>
          {forgotLoading ? 'Sending...' : 'Send Reset Email'}
        </button>
      </form>
      <a href="/signin">Back to Sign In</a>
    </div>
  );
}

Error Handling

function ForgotPasswordWithErrors() {
  const { forgotPassword, loading, error } = useForgotPassword();
  const [customError, setCustomError] = useState('');

  const handleSubmit = async (email) => {
    setCustomError('');
    
    const result = await forgotPassword(email);
    
    if (result.errors) {
      // Handle specific error types
      const errorCode = result.errors[0]?.code;
      
      switch (errorCode) {
        case 'user_not_found':
          setCustomError('No account found with this email address');
          break;
        case 'rate_limit_exceeded':
          setCustomError('Too many attempts. Please try again later.');
          break;
        default:
          setCustomError('An error occurred. Please try again.');
      }
    }
  };

  return (
    <div>
      {(error || customError) && (
        <div className="error-message">
          {customError || error.message}
        </div>
      )}
      {/* Form implementation */}
    </div>
  );
}

Auto-Submit OTP

function AutoSubmitResetForm({ email }) {
  const { resetPassword, loading } = useResetPassword();
  const [otp, setOtp] = useState('');
  const [password, setPassword] = useState('');

  // Auto-submit when OTP is complete
  useEffect(() => {
    if (otp.length === 6 && password) {
      handleAutoSubmit();
    }
  }, [otp, password]);

  const handleAutoSubmit = async () => {
    await resetPassword(email, otp, password);
  };

  return (
    <div>
      <input
        type="text"
        value={otp}
        onChange={(e) => setOtp(e.target.value.replace(/\D/g, '').slice(0, 6))}
        placeholder="Enter 6-digit code"
        maxLength="6"
      />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="New password"
      />
      {loading && <p>Resetting password...</p>}
    </div>
  );
}

Notes

  • Reset codes are typically valid for 10-15 minutes
  • The email contains a 6-digit verification code
  • Password requirements should match your deployment’s security settings
  • Rate limiting may apply to prevent abuse
  • The hooks handle loading states automatically
  • All operations return a consistent ApiResult format