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
Whether the forgot password request is in progress
Any error that occurred during the request
useResetPassword
Whether the password reset is in progress
Any error that occurred during the reset
Methods
forgotPassword()
Sends a password reset email to the specified address.
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.
The email address associated with the reset
The 6-digit verification code from the email
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