React函数组件使用Hooks时无法获取最新state状态如何解决?
问题根因
你遇到的问题核心来自两个疏漏:
- 校验逻辑仅在捕获到错误时更新
errors状态,校验通过的分支没有清空之前存储的错误,导致合法输入时仍然显示旧的错误提示 - React的状态更新是异步的,调用
setErrors后无法立即在同一作用域内拿到更新后的errors值,这也是你直接打印errors.length拿到旧值的原因
修复方案
不需要依赖useEffect监听状态来触发提交,直接让校验函数返回最新的校验结果即可,同时补全清空错误的逻辑:
- 修改
validate函数,补充校验通过时清空错误的逻辑,同时直接返回错误列表
const validate = async () => { try { await schema.validate(user, { abortEarly: false }) // 校验通过,清空历史错误 setErrors([]) return [] } catch(er){ const errList = [...er.errors] setErrors(errList) return errList } }
- 修改
handleSubmit函数,直接使用validate返回的最新结果判断是否要提交,避免读取异步更新的状态
const handleSubmit = async (e) => { e.preventDefault() // 直接拿到最新的校验结果,不用读状态的errors const latestErrors = await validate() if(latestErrors.length === 0){ alert("X") const response= await axios.post("https://reqres.in/api/login",user) console.log(response) } }
- 移除你之前用来监听
errors触发提交的useEffect,该逻辑会导致组件初始化时errors为空就触发一次无效的提交请求。
可选优化
你的Input组件统一用了type="text",密码输入框建议单独指定type="password"避免明文显示,修改调用处代码即可:
<Input type="password" name="password" onChange={handleInputChange} id="password" value={user.password} label="رمز عبور"/>
同时给Input组件的原生input标签绑定type属性:
<input type={this.props.type || "text"} onChange={this.props.onChange} name={this.props.name} id={this.props.id} className="form-control" value={this.props.value} />
内容的提问来源于stack exchange,提问作者bami
相关产品推荐
相关产品推荐

