2

I am trying to check 2 inputs values before handling the submit form. Each time I type a new character, the event returns the previous value isValid is true only if I type

password: 123 and confirmPassword: 1234

I have read this article https://www.freecodecamp.org/news/what-every-react-developer-should-know-about-state/ but I still don't understand why the event has the previous value instead of the current one.

const [password, setPassword] = useState();
const [confirmPassword, setConfirmPassword] = useState();
const [isValid, setValidity] = React.useState<boolean>(false);

const onChangePassword = (event: any) => {
    setPassword(event.target.value)
    validatePasswords();
    console.log(password)
}
const onChangeConfirmPassword = (event: any) => {
    setConfirmPassword(event.target.value)
    validatePasswords();
    console.log(confirmPassword)

}
const validatePasswords = () => {
    if (password && confirmPassword) {
        setValidity(password == confirmPassword)
        console.log('is valid? ', isValid, password, confirmPassword)
    }
}
user2004
  • 1,783
  • 4
  • 15
  • 42
  • 2
    Does this answer your question? [useState set method not reflecting change immediately](https://stackoverflow.com/questions/54069253/usestate-set-method-not-reflecting-change-immediately) – David Apr 04 '22 at 13:20

2 Answers2

4

Updating states are asynchronous in nature, meaning you don't see the updates immediately, in your case you are invoking the validatePasswords right after updating the state, and by the time the validatePasswords is executed the state might have not been updated, hence you are seeing the previous value. To get the latest updated value and make comparisons thus after, you could make use of useEffect hook with the dependency of the state in which you're interested. Since the useEffect hook with a dependency array invokes only when there's a change in the state, this could be rightly used to accomplish your task.

useEffect(()=>{
//Run the function when the confirmPassword value is updated.
validatePasswords()
},[confirmPassword]) //<--Dependency array set to confirmPassword, meaning this hook is triggered whenever the value of confirmPassword is changed.

Your code after implementing useEffect should look like this:

const [password, setPassword] = useState();
const [confirmPassword, setConfirmPassword] = useState();
const [isValid, setValidity] = React.useState<boolean>(false);


useEffect(()=>{
 validatePasswords()
},[password,confirmPassword])

const onChangePassword = (event: any) => {
    setPassword(event.target.value)
    //Calling the above state updating function updates the state and triggers the useEffect hook which further calls the validatePassword function with the latest states.
    
}
const onChangeConfirmPassword = (event: any) => {
    setConfirmPassword(event.target.value)

}
const validatePasswords = () => {
    if (password && confirmPassword) {
        setValidity(password == confirmPassword)
        console.log('is valid? ', isValid, password, confirmPassword)
    }
}
Prajwal Kulkarni
  • 1,480
  • 13
  • 22
0

The issue is that you are doing the console.log() inside the function in which you are setting the state, and that's why you are getting an old value.

You just have to call the console the useState value, outside the function to get the correct value.

const [password, setPassword] = useState();
const [confirmPassword, setConfirmPassword] = useState();
const [isValid, setValidity] = React.useState<boolean>(false);

console.log(confirmPassword);
console.log(password);
console.log('is valid? ', isValid, password, confirmPassword)

const onChangePassword = (event: any) => {
    setPassword(event.target.value)
    validatePasswords();
}
const onChangeConfirmPassword = (event: any) => {
    setConfirmPassword(event.target.value)
    validatePasswords();
}
const validatePasswords = () => {
    if (password && confirmPassword) {
        setValidity(password == confirmPassword)
    }
}