How to validate password and confirm password in react hook form? Is there any validate property and message in react hook form to show errors?
Asked Answered
T

5

24

Actually, I try to validate the form and Stucked to validate the password and confirm the password.. is there any property in useForm to validate the password and show a message in react hook form in the latest version. please help. Actually, I try to validate the form and Stucked to validate the password and confirm the password.. is there any property in useForm to validate the password and show a message in react hook form in the latest version. please help.


import React, { useState } from 'react'
import Image from '../../../Components/UI/Images/Image'
import SubmitButton from '../../../Components/UI/Button/Button'
import {useForm} from 'react-hook-form'
import illustrate from '../../../Assets/Imagesused/resetpass.png'
import '../Login/Login.css'
import "./CreatePass.css"
import "../ChangePassword/ChangePass.css"

const CreatePass = () => {

//show password
const [toggle1, setToggle1] = useState(false);
const [toggle2, setToggle2] = useState(false);
let password;

const { register, handleSubmit, formState: { errors }, reset,watch,getValues } = useForm({
    mode: "onTouched"
});
password = watch("password", "");

const onSubmit = (data) => {
    
    console.log(data);
    reset();
}


return (
    <div className='Container'>
        <div className='illustration-box'>
            <Image imge={illustrate}/>
        </div>
        <div>
            <form className='Login-Box' onSubmit={handleSubmit(onSubmit)}>
                <div className='Heading1'>
                    <h1 className='Login-Heading'>Create Password</h1>
                </div>
                
                <div className='type-box1'>
                    <div className='Label1'>
                        <label >
                         Password
                        </label>
                    </div>
                    <div className='input1'>
                        <i id="passlock" className="fa fa-lock icon"></i>
                        <i id="showpass" className="fa fa-eye icon" onClick={() => { setToggle1(!toggle1) }}></i>
                        <input className='input-field' size={"44"} type={toggle1 ? "text" : "password"} placeholder='Password' name="password" {...register("password", { required: "**Password is required", minLength: { value: 4, message: "**Password must be more than 4 characters" }, maxLength: { value: 12, message: "**Password cannot exceed more than 12 characters" }})}></input>
                    </div>
                    <p className='alerts'>{errors.password?.message}</p>
                    <div className='Label2'>
                        <label >
                           Confirm Password
                        </label>
                    </div>
                    <div className='input2'>
                        <i id="passlock" className="fa fa-lock icon"></i>
                        <i id="showpass" className="fa fa-eye icon" onClick={() => { setToggle2(!toggle2) }}></i>
                        <input className='input-field' size={"44"} type={toggle2 ? "text" : "password"} placeholder='Password' name="cpassword" {...register("cpassword", { required: "**Password is required" },{validate: (value) => value === getValues("password")})}></input>
                    </div>
                    <p className='alerts'>{errors.cpassword?.message}</p>
                    <div className='Button'>
                        <SubmitButton className="Login-Button4" Label="Proceed"  ></SubmitButton>
                    </div>
                </div>
                
            </form>

        </div>

    </div>
)
}

export default CreatePass
Tallahassee answered 25/12, 2021 at 15:19 Comment(0)
P
17

You should use yup and @hookform/resolvers for validation definitions to easily configure it.

  const formSchema = Yup.object().shape({
    password: Yup.string()
      .required("Password is required")
      .min(4, "Password length should be at least 4 characters")
      .max(12, "Password cannot exceed more than 12 characters"),
    cpassword: Yup.string()
      .required("Confirm Password is required")
      .min(4, "Password length should be at least 4 characters")
      .max(12, "Password cannot exceed more than 12 characters")
      .oneOf([Yup.ref("password")], "Passwords do not match")
  });

const {
    register,
    handleSubmit,
    formState: { errors },
    reset,
    watch,
    getValues
  } = useForm({
    mode: "onTouched",
    resolver: yupResolver(formSchema)
  });

And change register calls to only contain the name of the filed.

<input
    ...
    ...
    {...register("password")}
></input>

<input
    ...
    ...
    {...register("cpassword")}
></input>

Code sandbox => https://codesandbox.io/s/summer-glade-pjg06?file=/src/App.js

Pilcomayo answered 25/12, 2021 at 16:43 Comment(4)
@hargun singh, check this out !!Pilcomayo
Thank you so much I understandTallahassee
This won't work if you type in password confirm and then go back in first password field and type the same password.Weldon
Why use yup when validation is built into RHF?Wilt
S
74

You can do this with react hook forms alone. You can use watch from react hook form to get this done. This lets you listen for changes in the password field, which you can use in your confirm password validate method to compare the password with the confirm password field value as show below;

const {register, watch} = useForm();
<input
 {...register("password", {
  required: true
 })}
/>
<input
 {...register("confirm_password", {
  required: true,
  validate: (val: string) => {
    if (watch('password') != val) {
      return "Your passwords do no match";
    }
  },
 })}
/>
Saucier answered 10/3, 2022 at 19:48 Comment(3)
When changing the password after entering both the password and password confirmation, the validation doesn't occur correctly. To address this, even after triggering trigger("passwordConfirm") when entering the password, it doesn't work as intended. Is there any solution available? Please refer to the link below. codesandbox.io/s/…Equity
Its working for me, I made changes so that it matches my answer codesandbox.io/s/…Saucier
It seems to be behaving a little strangely. Go to the link you provided and in the results in the browser 1. Enter “abc” in the Password field. 2. On the PasswordConfirm page Enter “abcd” 3. Add “d” to the Password page If you do this There is still a validation error in PasswordConfirm.Equity
P
17

You should use yup and @hookform/resolvers for validation definitions to easily configure it.

  const formSchema = Yup.object().shape({
    password: Yup.string()
      .required("Password is required")
      .min(4, "Password length should be at least 4 characters")
      .max(12, "Password cannot exceed more than 12 characters"),
    cpassword: Yup.string()
      .required("Confirm Password is required")
      .min(4, "Password length should be at least 4 characters")
      .max(12, "Password cannot exceed more than 12 characters")
      .oneOf([Yup.ref("password")], "Passwords do not match")
  });

const {
    register,
    handleSubmit,
    formState: { errors },
    reset,
    watch,
    getValues
  } = useForm({
    mode: "onTouched",
    resolver: yupResolver(formSchema)
  });

And change register calls to only contain the name of the filed.

<input
    ...
    ...
    {...register("password")}
></input>

<input
    ...
    ...
    {...register("cpassword")}
></input>

Code sandbox => https://codesandbox.io/s/summer-glade-pjg06?file=/src/App.js

Pilcomayo answered 25/12, 2021 at 16:43 Comment(4)
@hargun singh, check this out !!Pilcomayo
Thank you so much I understandTallahassee
This won't work if you type in password confirm and then go back in first password field and type the same password.Weldon
Why use yup when validation is built into RHF?Wilt
D
10

Try the below for 7.x that works for me

const {
    register,
    getValues,
  } = useForm();

<input
   
    {...register("password")}
></input>
<input
    {...register("cpassword",  validate: (value) => {
              const { password } = getValues();
              return password === value || "Passwords should match!";
            })}
></input>
Dacosta answered 11/3, 2022 at 0:9 Comment(2)
where I'm supposed to catch the message "Passwords should match!" once the validation fails?Burns
@Burns error message should be part of the form errors in the form state which you can show on the screen for the user. where you destructured the rgeister method etc. const { register, formState:{errors} , getValues, } = useForm(); Dacosta
E
5

Adding to Amila Senadheera answer and to answer llcho Talesky, "if you type in password confirm and then go back in the first password field and type the same password".

    const {
    register,
    handleSubmit,
    formState: { errors },
    reset,
    watch,
    trigger,
    getValues
  } = useForm({
    mode: "onTouched",
    resolver: yupResolver(formSchema)
  });

const password = watch("password");
  useEffect(() => {
    trigger("cpassword");
  }, [password, trigger]);

So in the code using useEffect changes to the password field is monitored and using it validation on confirm password is triggered

Encincture answered 9/5, 2022 at 0:45 Comment(1)
maybe it's not necessary to use trigger in useEffect's dependencies.Bryon
C
2
 <FormControl isInvalid={errors.confirmPassword}>
            <FormLabel>Confirm Password</FormLabel>
            <Input type="password" {...register("confirmPassword", { 
              required: true,
              validate: (value) => value === watch("password") || "Passwords do not match"
            })} />
            <FormErrorMessage>{errors.confirmPassword && errors.confirmPassword.message}</FormErrorMessage>
          </FormControl>
Ciliata answered 17/5, 2023 at 11:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.