Skip to main content

Overview

useUpdateUserPasswordWithCode hook is used to handle the process of updating a user’s password using a verification code. It leverages the react-query library to manage the asynchronous operation and provides error handling and success callbacks.
useUpdateUserPasswordWithCode is responsible for password updating for users who requested verification code by email in using useRequestForgotPasswordCodeByEmail hook.

Example Usage

update-password-with-code-component.tsx
import { useState } from 'react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { REGEXP_ONLY_DIGITS_AND_CHARS } from 'input-otp';

import { HttpError } from '@locai1/iam-javascript';
import { useUpdateUserPasswordWithCode } from '@locai1/iam-react';

import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form';
import { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot } from '@/components/ui/input-otp';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';

const formSchema = z.object({
  code: z.string().min(6, {
    message: "Your one-time password must be 6 characters.",
  }),
  password: z.string().min(8, {
    message: 'Password must be at least 8 characters',
  })
  .refine(
    (password) => /[A-Z]/.test(password),
    { message: "Password must contain at least one uppercase letter" }
  )
  .refine(
    (password) => /[a-z]/.test(password),
    { message: "Password must contain at least one lowercase letter" }
  )
  .refine(
    (password) => /[0-9]/.test(password),
    { message: "Password must contain at least one number" }
  )
  .refine(
    (password) => /[^A-Za-z0-9]/.test(password),
    { message: "Password must contain at least one special character" }
  ),
  confirmPassword: z.string().min(1),
})
.superRefine(({ confirmPassword, password }, ctx) => {
  if (confirmPassword !== password) {
    ctx.addIssue({
      code: "custom",
      message: "Passwords must match",
      path: ['confirmPassword']
    });
  }
});

type FormSchemaType = z.infer<typeof formSchema>;

type UpdatePasswordFormProps = {
  onComplete: () => void;
  email: string;
};

export const UpdatePasswordWithCodeComponent = ({ onComplete, email }: UpdatePasswordFormProps) => {
  const [error, setError] = useState<HttpError | Error>();

  const { updateUserPassword } = useUpdateUserPasswordWithCode({
    onError: setError,
    onSuccess: onComplete,
  });

  const form = useForm<FormSchemaType>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      code: "",
      password: "",
      confirmPassword: "",
    },
  })

  const handleSubmit = form.handleSubmit(async (data: FormSchemaType) => {
    updateUserPassword({
      email,
      newPassword: data.password,
      verificationCode: data.code,
    });
  });

  return (
    <Form {...form}>
      <form onSubmit={handleSubmit}>
        <FormField
          control={form.control}
          name="code"
          render={({ field }) => (
            <FormItem>
              <FormControl>
                  <InputOTP
                    maxLength={6}
                    pattern={REGEXP_ONLY_DIGITS_AND_CHARS}
                    {...field}
                  >
                    <InputOTPGroup>
                      <InputOTPSlot index={0} />
                      <InputOTPSlot index={1} />
                      <InputOTPSlot index={2} />
                    </InputOTPGroup>
                    <InputOTPSeparator />
                    <InputOTPGroup>
                      <InputOTPSlot index={3} />
                      <InputOTPSlot index={4} />
                      <InputOTPSlot index={5} />
                    </InputOTPGroup>
                  </InputOTP>
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <FormField
          control={form.control}
          name="password"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Password</FormLabel>
              <FormControl>
                <Input type="password" required {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <FormField
          control={form.control}
          name="confirmPassword"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Confirm Password</FormLabel>
              <FormControl>
                <Input type="password" required {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        {error?.message}
        <Button type="submit">Update Password</Button>
      </form>
    </Form>
  );
};

Parameters

onSuccess
() => void
required
callback function that is called when the password update process is successful.
onError
HttpErrorCallback
required
callback function that is called when an error occurs during the password update process.
HttpErrorCallback type
type HttpErrorCallback = (error: HttpError | Error | undefined) => void;

Returns

updateUserPassword
(payload: UpdatePasswordWithCode) => void
function that triggers the password update process with the provided payload.
UpdatePasswordWithCode type
type UpdatePasswordWithCode = {
  email: string;
  newPassword: string;
  verificationCode: string;
};
isLoading
boolean
boolean indicating whether the password update process is currently in progress.
isError
boolean
boolean indicating whether an error occurred during the password update process.
error
HttpError | Error | null
error object if an error occurred during the password update process.