ReactJS项目中表单提交按钮需点击两次才生效的问题该如何修复?
React表单提交重复点击才跳转问题修复方案
问题原因
React的setSubmitted是异步更新函数,状态更新后要等到下一次组件渲染才会生效。同时handleSubmit函数内部的submitted变量被当前渲染周期的闭包捕获,值是固定的:
- 第一次点击提交时,闭包内的
submitted是初始值false,调用setSubmitted(true)后状态没有立即更新,后续判断if (submitted)拿到的还是旧值,跳转逻辑不触发 - 第二次点击提交时,上一次更新的
submitted: true已经在新的渲染周期生效,闭包内的submitted值为true,判断成立所以可以跳转
修复方案
方案1:直接在请求成功后执行跳转(最推荐)
你的需求本身就是提交成功后直接跳转,不需要额外依赖submitted状态做判断,直接简化代码即可:
import { useHistory } from 'react-router-dom'; import { useState } from 'react'; function OrderForm() { const history = useHistory(); const handleSubmit = (e) => { e.preventDefault(); fetch('http://localhost:8000/orders', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ cart: 1 }), // 替换为实际表单数据 }) .then((response) => { if (!response.ok) throw new Error('提交请求失败'); return response.json(); }) .then(() => { // 提交成功直接跳转,不需要判断状态 history.push('/thank-you-page'); }) .catch((err) => { // 增加错误处理,给用户失败提示 console.error('提交出错:', err); alert('订单提交失败,请稍后重试'); }); }; return ( <form onSubmit={handleSubmit}> {/* 表单内容 */} <button type="submit">提交订单</button> </form> ); }
方案2:保留submitted状态的修复方式
如果你的业务逻辑中确实需要submitted状态(比如控制提交按钮禁用、加载动画展示等),可以通过useEffect监听submitted的变化触发跳转:
import { useHistory } from 'react-router-dom'; import { useState, useEffect } from 'react'; function OrderForm() { const history = useHistory(); const [submitted, setSubmitted] = useState(false); const [loading, setLoading] = useState(false); // 监听submitted状态变化,为true时执行跳转 useEffect(() => { if (submitted) { history.push('/thank-you-page'); } }, [submitted, history]); const handleSubmit = (e) => { e.preventDefault(); setLoading(true); fetch('http://localhost:8000/orders', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ cart: 1 }), // 替换为实际表单数据 }) .then((response) => { if (!response.ok) throw new Error('提交请求失败'); return response.json(); }) .then(() => { setSubmitted(true); }) .catch((err) => { console.error('提交出错:', err); alert('订单提交失败,请稍后重试'); setLoading(false); }); }; return ( <form onSubmit={handleSubmit}> {/* 表单内容 */} <button type="submit" disabled={loading}> {loading ? '提交中...' : '提交订单'} </button> </form> ); }
内容的提问来源于stack exchange,提问作者Olsza100
相关产品推荐
相关产品推荐

