I have a problem (in React):
After the fetch occurs, when I console.log the User_ID value it shows me the right updated id value which is 1, but when I set the state of UserID and then I console.log it, it still shows me the default value which is 0 and not the updated one which equals to 1. Can someone please take a look in my code and tell me where the problem is? And if the problem is delay, can someone tell me how to fix it?
The code:
export default function Login() {
const [Email, setEmail] = useState("");
const [UserID, setUserID] = useState(0);
const [Password, setPassword] = useState("");
const navigate = useNavigate();
const btnLogin = async () => {
console.log(1);
console.log(Email "," Password);
let s = await checkUserDetails(
Email,
Password
);
console.log("returned value=" s "and id = " s.User_ID); //here the it returns the right User ID ( id = 1)
setUserID(s.User_ID) // for some reason here it doesnt update the right value of the User ID
if (s != null)
{
console.log("user_id is =" UserID); // here it still prints User ID = 0 .. why?
alert("Logged In Successfully!!");
navigate('/')
console.log("h1");
} else {
console.log("err login!");
alert("failed to login");
}
};
const checkUserDetails = async (Email, Password) => {
console.log("we are in func checkUserDetails, email = " Email);
try {
let result = await fetch(url `?email=${Email}&pass=${Password}`, {
method: "GET", // 'GET', 'POST', 'PUT', 'DELETE', etc.
headers: new Headers({
"Content-Type": "application/json",
Accept: "application/json",
}),
});
let resultData = result.json();
console.log("meowwww");
console.log(resultData);
if (resultData) {
return resultData;
} else {
alert("unable to login");
}
} catch (e) {
console.log("Error Login", e);
alert("lo mevin");
}
};
return (
<div className="login-form">
<button
type="button"
className="button-LoginSign"
onClick={btnLogin}
>
Login
</button>
</div>
Thanks for all the helpers
CodePudding user response:
that is because react state updates are not synchronous !!!!!
if you want to use the latest value inside the function where you are using you can directly use the response or create a useEffect with userId as a dependency
also your variable names should be camelCase - password, userId etc.
useEffect(()=> { this effect will have the latest value of ID}, [userId]
and will run whenever setUserId is called
CodePudding user response:
The UserId
piece of state will not show the updated value until the next render of that component. So in that initial run through the btnLogin
function it still has the original value. Use s.User_ID
there again if you need to. But I don't see that you really need access to that value other than a console log.
If you need to do something once that UserId has been set to state, put that inside a useEffect
useEffect(() => {
if (UserId > 0) {
// do something with id
}
}, [UserID])
CodePudding user response:
You can never get your updated state this way. Because, you are writing console statement write after setUserId() hook, Which is asynchronous in nature. To get the updated value you need to write a useEffect hook with the state in dependency array like this. So whenever you set UserID the updated state will be reflected in this useEffect.
useEffect(()=>{
console.log(userId)
//Now desired computation on base of updated state
},[userId])