I want my react states to be updated immediately as soon as I refactor the data in them so that I can run the functions in correct order, otherwise, when it performs the next function I declared, it will just execute the undefined
or null
data since its not yet updated.
How can I fix this issue? I know some will say that states are not made for this and have to be used asynchronously but I don’t know how I can else make that work out and let the users get logged in and redirect to their profile page only when they type correct users credentials, this might not sound a big deal for most of you but I’m just new to react and have been dealing with that for the last few days passed, basically users should be able to granted for the profile page only when they successfully log in and otherwise should get an error..
But, to get it running perfectly, currentUser
has to be populated through the credentials taken from the userInput
and passInput
states just before the next function, which is useEffect
, feeling so stuck with that and any help will be very appreciated
https://github.com/Abdulberk/frontend-auth
type User = { username: String | null; password: String | null; } function Login() { const [userInput, setUserInput] = useState<String | null>(""); const [passInput, setPassInput] = useState<String | null>(""); const [isLoggedin, setIsLoggedin] = useState<Boolean>(false); const [isLoading, setIsLoading] = useState<Boolean>(false) const [error, setError] = useState<Boolean>(false); const [count, setCount] = useState(0); const [auth, setAuth] = useState<String | null>(""); const navigate = useNavigate(); const [currentUser, setCurrentUser] = useState<User>({ username: "", password: "" }); const submitHandler = (event: React.MouseEvent<HTMLButtonElement>): void => { event.preventDefault(); setIsLoading(true); setCurrentUser(prev => { return { ...prev, username: userInput, password: passInput } }); setCount(prev => prev + 1) } useEffect(() => { axios.post("https://reqres.in/api/login", { email: currentUser.username, password: currentUser.password }) .then((response: AxiosResponse<any, any>) => { console.log(response) if (response.status === 200) { console.log("user exists"); setIsLoading(false); setIsLoggedin(true) setAuth(response.data.token) setCount(prev => prev + 1) } else { console.log("user does not exist"); setIsLoading(false); setIsLoggedin(false); setAuth(null) setCount(prev => prev + 1) } }) .catch((error: any) => { setAuth(prev => prev) setIsLoggedin(false) setIsLoading(false); setCount(prev => prev + 1) }) }, [currentUser.username, currentUser.password]) if (isLoggedin) { setTimeout(() => { console.log("redirecting to profile page"); navigate(`users/${currentUser.username}`, { state: currentUser }); }, 2000); } useEffect(() => { console.log(`${count} renders`); }, [count]) return ( <div> <Form> <LoginContainer> <LoginImageContainer> <LoginImage src={require('../right.png')}/> </LoginImageContainer> <LoginTitle>Login your account</LoginTitle> <InputContainer > <FaUserCircle fontSize="30px" color="#747474" style={{ position: "absolute", top: "50%", transform: "translateY(-50%)", left: "20px" }} /> <LoginInput onChange={(e: React.ChangeEvent<HTMLInputElement>) => setUserInput(e.target.value)} placeholder="Username" /> </InputContainer> <InputContainer > <RiKeyFill style={{ left: "20px", top: "50%", transform: "translateY(-75%)", color: "#747474", fontSize: "32px", position: "absolute" }} /> <LoginInput placeholder="Password" style={{ marginBottom: "20px" }} onChange={(e: React.ChangeEvent<HTMLInputElement>) => setPassInput(e.target.value)} /> </InputContainer> <Button onClick={submitHandler} className={isLoading? 'lds-dual-ring': undefined} type='submit' style={{ backgroundColor: "#7FBCD2", marginBottom: "20px" }} size="lg" variant="primary" > {!isLoading ? "Login" : undefined} </Button> </LoginContainer> </Form> </div> ) } export default Login;
Advertisement
Answer
Alright I gave it a try even though your sandbox was empty. Check it out here. It’s a stripped out version of what you shared here.
The gist of it is that your login attempt pattern is odd. The submit handler should be submitting the login with the current state and the input onChange should be updating the currentUser directly.
On top of that your redirect should be handled in a useEffect. Let me know if you have questions or I missed something!