如何检测React中的表单是否成功提交以触发后续请求?
React隐藏iframe表单提交状态检测方案
核心问题说明
你当前使用的原生form.submit()方法没有内置回调机制,且3DS ACS接口一般为跨域服务,无法直接读取iframe内部返回内容判断提交结果,可通过以下方案实现状态监听:
实现方案
方案1:监听iframe加载完成事件(适用不需要拿到返回结果,仅需确认提交完成的场景)
- 新增提交状态标记,区分iframe初始加载和提交后的加载
- 给iframe绑定
onLoad事件,提交触发后的加载事件即代表表单提交动作已完成 - 已修正你原代码中form的
target与iframe的name不匹配的问题,避免表单提交弹出新窗口
修改后代码如下:
const formRef = React.useRef<HTMLFormElement>(null); const iframeRef = React.useRef<HTMLIFrameElement>(null); // 标记是否已发起提交 const [isSubmitted, setIsSubmitted] = React.useState(false); // 标记是否提交完成 const [isSubmitSuccess, setIsSubmitSuccess] = React.useState(false); useEffect(() => { if (formRef?.current) { setIsSubmitted(true); formRef.current.submit(); } }, [formRef]); return ( <> <form id="tdsMethodAcs" method="post" target="tdsMethodAcsFrame" action={three_ds_method_url} style={{ display: "none" }} ref={formRef} > <input type="hidden" name="methodAcsFrame" value={method_data_packed} /> <input type="submit" /> </form> <iframe name="tdsMethodAcsFrame" width="0" height="0" ref={iframeRef} onLoad={() => { if (isSubmitted) { setIsSubmitSuccess(true); // 此处可发起后续表单的请求 } }} ></iframe> </> )
方案2:配合后端回调拿到准确提交结果(适用需要校验3DS返回结果的场景)
- 要求3DS服务端完成处理后,跳转到你指定的同域回调页面
- 回调页面通过
postMessage给父页面发送提交结果,父页面监听message事件获取结果
示例监听代码:
useEffect(() => { const handleMessage = (e) => { // 校验来源是你指定的回调域名,防止恶意消息 if (e.origin === window.location.origin && e.data.type === '3dsSubmitResult') { if (e.data.success) { // 提交成功,发起后续请求 setIsSubmitSuccess(true); } else { // 提交失败处理逻辑 } } } window.addEventListener('message', handleMessage); return () => window.removeEventListener('message', handleMessage); }, [])
注意事项
- 跨域iframe默认不允许父页面读取内部DOM和内容,没有后端配合的前提下只能通过
onLoad判断提交动作完成,无法判断业务逻辑是否成功 - 若使用方案2必须校验消息来源
origin,避免安全风险
内容的提问来源于stack exchange,提问作者Sunstrike527
相关产品推荐
相关产品推荐

