1

I'm trying to make a form with React but having some issues with the password and confirm password field.

What I want is basically to have a user type a password and once they confirm, it should display in real time whether the password matches the confirm password field, or if the passwords do not match.

    const handlePasswordChange = (event) => {

        const { name, value } = event.target;

        setCustomerData(prev => ({
             ...prev,
              [name]: value 
        }));

        // setPasswordError displays the error on the form to the user
        if(customer.password === customer.confirmPassword) {
            setPasswordError('passwords match')
        } else if(customer.password !== customer.confirmPassword) {
            setPasswordError('Passwords dont match')
        } else {
            setPasswordError('');
        }
        

        console.log("password: " + customer.password);
        console.log("Confirm password: " + customer.confirmPassword);
    }

State Object

    const [customer, setCustomerData] = useState({
        firstName: "",
        lastName: "",
        emailAddress: "",
        mobileNumber: "",
        dateOfBirth: new Date(),
        password: "",
        confirmPassword: ""
    });


    // Displays error using spring boot on the backend


----------


    const [firstNameError, setFirstNameError] = useState("");
    const [lastNameError, setLastNameError] = useState("");
    const [emailAddressError, setEmailAddressError] = useState("");
    const [mobileNumberError, setMobileNumberError] = useState("");
    const [dateOfBirthError, setDateOfBirthError] = useState("");
    const [passwordError, setPasswordError] = useState("");


Form password and confirm password fields

    {/*Password*/}
                    <div className="form-group">
                        <label htmlFor="password" className="register-form-labels">Password</label>

                        {passwordError ? <span className="field-validation-styling">{passwordError}</span> : ''}

                        <input type={passwordShown ? "text" : "password"} 
                            onFocus={(e) => setPasswordError('')}
                            className="shadow-none form-control register-form-input-field" 
                            name="password"
                            placeholder="Enter Password" 
                            value={customer.password} 
                            onChange={handlePasswordChange} 
                        />
                      
                    </div>

                    {/*Confirm Password*/}
                    <div className="form-group">
                        <label htmlFor="confirmPassword" className="register-form-labels">Confirm Password</label>

                        <input type={passwordShown ? "text" : "password"} 
                            minLength="8"
                            className="shadow-none form-control register-form-input-field" 
                            name="confirmPassword"
                            placeholder="Confirm Password" 
                            value={customer.confirmPassword} 
                            onChange={handlePasswordChange} />
                    </div>

But when i type in my password, the input is a character behind. This is what i mean

enter image description here

Andrew Lohr
  • 5,380
  • 1
  • 26
  • 38
ServletException
  • 171
  • 1
  • 15

1 Answers1

1

So useState doesn't update immediately, you need something to listen to the changes and update afterwards.

As you are calling handlePasswordChange on change, and then in the same function checking for equality, the customer state is still the "old" state. It wont become the "new" state until reload.

The use of useEffect would be fine here, listening for changes in the customer object, and then acting upon them;

// Function to set passwords

const handlePasswordChange = (event) => {
        const { name, value } = event.target;
        setCustomerData((prev) => ({
        ...prev,
       [name]: value
       }));

// setPasswordError displays the error on the form to the user

    console.log("password: " + customer.password);
    console.log("Confirm password: " + customer.confirmPassword);
};

//useEffect with a dependency of customer

useEffect(
    (_) => {
      checkPassword(customer);
    },
    [customer]
  );

// separate check password function

  const checkPassword = (customer) => {
    if (customer.password === customer.confirmPassword) {
      setPasswordError("passwords match");
    } else if (customer.password !== customer.confirmPassword) {
      setPasswordError("Passwords dont match");
    } else {
      setPasswordError("");
    }
  };
ShatteredDev
  • 491
  • 3
  • 9
  • Thank you, it works. I am still new to react as you can tell and i was considering to use a useEffect hook here, but was not sure if there was a better approach. – ServletException Sep 20 '21 at 21:12