我有一个用于用户登录的 React 表单,除了设置成功或不成功的消息外,一切正常。登录后,根据用户是否注册,我将 useState variable [res, setRes]
的值设置为成功或成功。问题是,即使用户已注册且用户名和密码正确,我也至少收到一次“无效凭据”消息。来自同一用户的后续调用会导致显示正确的消息。搜了一下,发现state落后一步,解决办法是用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。此外,语言是 Typescript。 谢谢
答案 0 :(得分:2)
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
。实际上,我可能甚至不会在这里使用,而是在设置 setToastIsShown
后从 send
内部调用 res
。当您有两个相关的数据片段由多个不相关的方法更新时,useEffect
真的会派上用场。