ES6环境下表单首次点击不提交,需实现先setState再提交的单次触发
解决React表单提交时State更新异步导致的首次点击失败问题
嘿,这问题我太熟了——React的状态更新是异步批量处理的,你第一次点击Submit时,setFormValidity只是把更新请求放进了队列,还没真正修改state,紧接着就执行提交操作,这时候读取到的formValidity还是旧值,自然提交失败;第二次点击时,上一次的state更新已经完成,所以就能成功了。
给你两种场景的解决方案,看你用的是类组件还是函数组件:
如果你用的是类组件
直接利用setState的第二个回调参数——这个回调会在state确实更新完成后执行,完美解决异步问题:
onSubmit = (e) => { e.preventDefault(); // 先阻止浏览器默认的表单提交行为 // 先完成你的表单验证逻辑,得到是否合法的结果 const isFormValid = /* 这里写你的验证代码,比如检查输入、格式等 */; // 用setState的回调确保状态更新后再提交 this.setState({ formValidity: isFormValid }, () => { // 这里的state已经是最新的了 if (this.state.formValidity) { // 执行你的邮件发送操作,尽量别用eval,换成直接调用函数更安全 // eval(你的邮件发送代码); // 或者如果需要提交原生表单的话: e.target.submit(); } }); };
如果你用的是函数组件(useState)
useState没有内置的回调,但可以用useEffect监听formValidity的变化,当它变为true时执行提交:
import { useState, useEffect } from 'react'; function YourFormComponent() { const [formValidity, setFormValidity] = useState(false); // 监听formValidity的变化,状态更新后触发 useEffect(() => { if (formValidity) { // 执行邮件发送操作 // eval(你的邮件发送代码); // 记得如果不需要保留这个状态,可以在这里重置: // setFormValidity(false); } }, [formValidity]); // 依赖项填formValidity,只有它变化时才执行 const onSubmit = (e) => { e.preventDefault(); const isFormValid = /* 你的表单验证逻辑 */; setFormValidity(isFormValid); }; return ( <form onSubmit={onSubmit}> {/* 你的表单元素 */} <button type="submit">Submit</button> </form> ); }
最后提个小建议:尽量避免使用eval,它不仅有安全风险(如果用户输入的内容被注入的话),还会影响代码的可维护性和性能,能换成直接调用函数就尽量换~
内容的提问来源于stack exchange,提问作者clusterBuddy
相关产品推荐
相关产品推荐

