React - useState returns initialized value even after manipulating it

Viewed 52

This is my code:

import React,{useEffect, useState} from 'react';
import bootstrap from '../../node_modules/Bootstrap/dist/css/bootstrap.min.css'
import '../ComponentStyles/NavbarStyle.css'
function Navbar() {
  const [LUsername,setLUsername]=useState('')
  const [LPassword,setLPassword]=useState('')
  const [IsLogin,setIsLogin]=useState(false)

  function Login(){

    let credentials = JSON.parse(localStorage.getItem('cred'))
    console.log(credentials)
    for(let i=0;i<credentials.length;i++) {

      if(credentials[i].username===LUsername && credentials[i].password===LPassword){
        alert('in')
        // why does IsLogin value is false even after setting it to true
        setIsLogin(false)
        alert(IsLogin)
      }

    }
    if(IsLogin){
      alert('login')
    }

    else{
      alert('Login Failed')
    }

On line 7 I have initialized Islogin variable with useState. On line 18 I am using the setIsLogin method to change it's initial value from false to true

but when I use alert to output it's value it gives me the initial value which is false. Also the value returned is true when I use conditional rendering in line 45, It works correct over there, Can someone tell me why the value is shown wrong in alert? Thanks.

3 Answers

Returns a stateful value, and a function to update it. The function to update the state can be called with a new value or with an updater function argument.

As you can see your code, state right after calling setState will have value before the update.

We have some options. Calling updater just to get the latest value.

const [value, setValue] = useState(false);
setValue(true);
setValue((state) => {
  console.log(state); // true
  
  return state;
});

Custom hook for setState with async state selector.

const [value, setValue, getValue] = useSetState(false);
setValue(true);
console.log(await getValue()); // true

You can try to use useEffect to output IsLogins value when the value changes.

useEffect(() => {
    alert(IsLogin)
  },[IsLogin]);

insert this snippet right under "const [IsLogin, setIsLogin] = useState(false)"

According to React's documentation:

State Updates May Be Asynchronous

React may batch multiple setState() calls into a single update for performance.

You can not relay on setState to mutate the state synchronously. In order to do something (effect), you should use useEffect on that state variable.

Related