React中为什么要点击两次Submit按钮才能更新useState钩子状态?
问题原因
- React中
useState的状态更新函数是异步的,调用setAuthenticate后,当前函数执行上下文内的authenticate不会立即更新,新的状态值只会在组件下一次渲染时生效。 - 你的代码中调用
setAuthenticate(res.data)后立刻执行authentication(),此时读取的authenticate仍是本次渲染的旧值(初始为null),因此判断逻辑不会生效。第二次点击提交时,authenticate已经是上一次更新后的值,所以才会触发对应逻辑,就出现了需要点击两次的问题。
解决方法
有两种常用的修复方案:
方案1:直接使用接口返回结果判断跳转
不需要等待本地状态更新,直接拿接口返回的认证结果做跳转判断,修改newUser函数即可:
const newUser = (event) =>{ event.preventDefault() axios({ method: "POST", url: 'xxxxxxxxxxxxxxxxx', data:{ username, password } }).then(res=>{ const authResult = res.data setAuthenticate(authResult) console.log(authResult) // 直接用接口返回结果判断,不依赖当前作用域的旧状态 authResult ? navigate("/dashboard") : console.log('Cannot create User') }) }
同时可以删除原本的authentication函数,不需要额外定义。
方案2:通过useEffect监听状态变化触发跳转
如果后续逻辑需要依赖authenticate状态,可以用useEffect监听它的变化,状态更新后自动执行跳转逻辑:
- 新增监听
authenticate的useEffect:
useEffect(() => { // 初始为null时不执行逻辑 if (authenticate === null) return authenticate ? navigate("/dashboard") : console.log('Cannot create User') }, [authenticate, navigate])
- 简化
newUser函数,移除后续的状态读取和跳转调用:
const newUser = (event) =>{ event.preventDefault() axios({ method: "POST", url: 'xxxxxxxxxxxxxxxxx', data:{ username, password } }).then(res=>setAuthenticate(res.data)) }
额外优化建议
你代码中的密码输入框type设为了text,输入时会明文显示,建议修改为type="password"提升安全性。
内容的提问来源于stack exchange,提问作者M H
相关产品推荐
相关产品推荐

