React中等待setState完成后调用handleLogin解决二次点击登录问题
解决登录按钮需点击两次的问题
你的问题核心是setState是异步操作:在handleSubmitLogIn里调用setCredentials后立刻执行handleLogIn,此时credentials还没更新到最新的表单值,导致第一次调用handleLogIn时用的是旧的state,验证逻辑无法正确执行;第二次点击时state完成更新,才能拿到正确凭证完成登录流程。
下面提供两种可行的解决办法:
方案一:直接传递表单值给handleLogIn(推荐)
跳过state依赖,直接把刚获取的用户名和密码作为参数传给handleLogIn,彻底避开异步更新的问题:
const [validationState, setValidationState] = useState() const navigate = useNavigate() const handleLogIn = (credentials) => { console.log(credentials) userValidation(credentials) .then((response) => { console.log(response) setValidationState(response) }) } useEffect(() => { if (validationState) { localStorage.setItem('islogged', true) navigate('/database-filler') } else { localStorage.setItem('islogged', false) } }, [validationState, navigate]) const handleSubmitLogIn = (event) => { event.preventDefault() const [username, password] = document.forms[0] const newCredentials = { user: username.value, password: password.value } // 直接传递最新的凭证给登录函数 handleLogIn(newCredentials) }
方案二:用useEffect监听credentials变化
如果必须依赖state触发登录逻辑,可以新增一个监听credentials的useEffect,当凭证更新且不为空时自动调用登录函数:
const [validationState, setValidationState] = useState() const [credentials, setCredentials] = useState({}) const navigate = useNavigate() const handleLogIn = () => { console.log(credentials) userValidation(credentials) .then((response) => { console.log(response) setValidationState(response) }) } useEffect(() => { if (validationState) { localStorage.setItem('islogged', true) navigate('/database-filler') } else { localStorage.setItem('islogged', false) } }, [validationState, navigate]) // 新增监听:当credentials更新且有有效值时执行登录 useEffect(() => { if (credentials.user && credentials.password) { handleLogIn() } }, [credentials]) const handleSubmitLogIn = (event) => { event.preventDefault() const [username, password] = document.forms[0] setCredentials({ user: username.value, password: password.value }) // 此处不再直接调用handleLogIn }
方案一更高效,无需等待state更新即可使用最新表单值;方案二则适合必须依赖state的场景,注意添加条件判断避免不必要的重复调用。
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

