Javascript 尽管效果不佳,但反应状态落后一步
我有一个用户登录的React表单,除了设置成功或不成功的消息外,一切正常。登录后,我将useState变量[res,setRes]的值设置为successful或ususessful,具体取决于用户是否注册。问题是,即使用户已注册且用户名和密码正确,我至少和最多会收到一次无效凭据消息。来自同一用户的后续呼叫将显示正确的消息。我搜索发现state落后了一步,解决方案是使用useffect,但我已经在使用它了。有人能帮我找出问题所在吗?代码如下Javascript 尽管效果不佳,但反应状态落后一步,javascript,reactjs,typescript,ionic-framework,Javascript,Reactjs,Typescript,Ionic Framework,我有一个用户登录的React表单,除了设置成功或不成功的消息外,一切正常。登录后,我将useState变量[res,setRes]的值设置为successful或ususessful,具体取决于用户是否注册。问题是,即使用户已注册且用户名和密码正确,我至少和最多会收到一次无效凭据消息。来自同一用户的后续呼叫将显示正确的消息。我搜索发现state落后了一步,解决方案是使用useffect,但我已经在使用它了。有人能帮我找出问题所在吗?代码如下 export const Login = () =&g
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}
/>
</>
)
}
我用的是爱奥尼亚,这就是为什么你会看到土司。此外,该语言是Typescript。
谢谢当一个组件挂载时,总是调用useEffect钩子,之后每次它的依赖项数组中的值发生变化时,都会调用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后从内部调用setToastIsShown。当您有两个相关的数据段,这些数据段由多个不相关的方法更新时,useEffect真的很有用。cred的初始状态是一个空对象,因为const[cred,setCred]=useState{}。如果这是无效的凭据,您将始终收到一个无效呼叫。是否应该仅在存在有效凭据时调用钩子?感谢您的回复。不,无论是否使用有效凭据,都无法调用该钩子。我尝试为cred硬编码有效的用户名密码,但存在相同的问题。