You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React表单未点击提交按钮却触发onSubmit的问题排查

点击Next按钮意外触发表单onSubmit的原因

问题复现代码

import { useState } from 'react'

export function App(props) {
  const [ready, setReady] = useState(false)

  function handleSubmit(e) {
    e.preventDefault()
    alert("Submitted!")
  }

  return (
    <form onSubmit={handleSubmit}>
      { ready ?
      <button type="submit">Submit</button> :
      <button type="button" onClick={() => setReady(true)}>Next</button> }
    </form>
  )
}

核心原因

React的DOM复用机制导致了这个异常:

  • 点击Next按钮时,onClick回调同步将ready设为true,React立即执行DOM更新
  • 由于前后两个元素都是<button>标签,React会复用同一个DOM节点,而非销毁旧节点重建新节点
  • 浏览器处理按钮点击的默认行为是连续流程:在onClick回调执行完成后,会检查当前按钮的type属性——此时React已经把按钮的type从button改成了submit,浏览器判定这是提交按钮,进而触发了表单的onSubmit事件

解决方案

推荐两种简单有效的解决方式:

  1. 给按钮添加唯一key,阻止DOM复用
    给两个按钮分别设置不同的key,让React识别它们是独立元素,从而销毁旧按钮、创建新按钮:
<form onSubmit={handleSubmit}>
  { ready ?
  <button key="submit-btn" type="submit">Submit</button> :
  <button key="next-btn" type="button" onClick={() => setReady(true)}>Next</button> }
</form>
  1. 拆分渲染逻辑,明确区分元素
    将按钮的渲染拆分为独立分支,通过容器元素或条件判断的结构让React自动识别不同元素:
<form onSubmit={handleSubmit}>
  {ready && <button type="submit">Submit</button>}
  {!ready && <button type="button" onClick={() => setReady(true)}>Next</button>}
</form>

内容的提问来源于stack exchange,提问作者Nathan Osman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 07:35:00