反应状态落后一步,尽管使用效果



我有一个用于用户登录的 React 表单,除了设置成功或不成功的消息外,一切正常。登录后,我将useState variable [res, setRes]的值设置为成功或失败,具体取决于用户是否已注册。问题是,即使用户已注册并且用户名和密码正确,我至少一次并且最多一次收到消息"凭据无效"。来自同一用户的后续调用会导致显示正确的消息。我搜索并发现状态落后一步,解决方案是使用useEffect,但我已经在使用它了。谁能帮我弄清楚问题是什么?代码如下

export const Login = () => {
const email = useField('string')
const password = useField('password')
const [cred, setCred] = useState({})
const send = (e:any) => {
e.preventDefault()
setCred({'email':email.value, 'password':password.value}) 
showToast()
}
const [toastIsShown, setToastIsShown] = useState(false);
const showToast = () => {
setToastIsShown(true);
}
const [res,setRes] = useState('')
const hook = () => {
axios
.post('http://localhost:5000/auth', cred)
.then(response => { 
console.log('response is ',response.data)
setRes('Login Successful')
})
.catch(err => {
console.log("error is ",err.response)
setRes('Invalid username or password')
})
}
useEffect(hook,[cred])
return (
<>
<form onSubmit = {send}>
<IonText>Enter Name</IonText>
<br />
<input {...email} />
<br />
<IonText>Enter Password</IonText>
<br />
<input {...password} />
<br />
<button>Send</button>
</form>
<IonToast
isOpen={toastIsShown}
onDidDismiss={() => setToastIsShown(false)}
message={res}
duration={3000}
/>
</>
)
}

我正在使用Ionic,这就是为什么你在那里看到Toast。此外,语言是打字稿。 谢谢

useEffect钩子总是在组件挂载时调用,之后每次在其依赖项数组中的值更改时调用。由于空对象可能不是有效的登录,因此在组件挂载时,您总是会得到不成功的尝试。您可以执行一些简单的验证,例如:

cred.email && cred.password && axios.post('http://localhost:5000/auth', cred)...

但是,问题的根源是您滥用useEffect。登录尝试(通常,在您的情况下)是一次性事件,而不是由于先前的重大操作而发生的副作用。此方案中的副作用发生在登录尝试之后,当您触发包含有关结果的通知的 Toast 时:

export const Login = () => {
const email = useField('string');
const password = useField('password');

const [res, setRes] = useState('');
const [toastIsShown, setToastIsShown] = useState(false);
const send = (e:any) => {
e.preventDefault();
const cred = {
email: email.value,
password: password.value
};
axios
.post('http://localhost:5000/auth', cred)
.then(response => { 
console.log('response is ',response.data)
setRes('Login Successful');
})
.catch(err => {
console.log("error is ",err.response)
setRes('Invalid username or password');
});
};
useEffect(() => {
res && setToastIsShown(true);
}, [res]);

return (
...
)
}

这只是为了演示更合理地使用useEffect。实际上,我什至可能不会在这里使用一个,而只是在设置res后从内部send调用setToastIsShown。当您有两个相关的数据片段通过多个不相关的方法更新时,useEffect确实会派上用场。

最新更新