React Hook Form嵌套场景下如何实现第二个表单独立提交
问题根因
HTML 标准原生不支持 <form> 元素嵌套,内层表单触发提交时,事件会沿DOM树向上冒泡,直接触发外层绑定的submit回调,这和React Hook Form本身的逻辑无关,是DOM事件机制+非法标签嵌套导致的行为。
另外你代码里useForm的mode配置存在语法错误:mode接收字符串值,合法值为onSubmit/onBlur/onChange/onTouched/all,不需要包裹在对象里;同时Controller组件的校验规则不能直接写required属性,要传入rules配置项。
修复方案
优先选择第一种符合规范的写法,从根源避免兼容问题:
- 方案1:移除嵌套form,改为平级结构(最推荐):把两个表单改为DOM层面的平级元素,完全符合HTML规范,布局层面可以用CSS调整视觉位置,实现和嵌套完全一致的展示效果。
- 方案2:保留视觉嵌套,去掉内层form标签,手动绑定按钮事件阻止冒泡:如果业务布局必须把校验区块放在主表单的视觉区域内,不要给内层校验区块套
<form>标签,直接给Check按钮绑定点击事件,触发内层表单提交逻辑的同时调用stopPropagation()阻止事件冒泡,就不会触发外层表单的提交。
注意:所有表单内的按钮如果不是用来触发当前表单提交的,都要显式加
type="button",因为form内的button默认type是submit,会自动触发最近层级form的提交事件,这是表单提交异常的高频诱因。
修正后代码示例
// 修正useForm的mode配置错误 const { register, handleSubmit, errors, control } = useForm({ mode: 'onBlur', }); const { register: register2, handleSubmit: handleSubmit2, errors: errors2, control: control2, } = useForm({ mode: 'onBlur', }); const onSubmit = (data) => { console.log('主表单提交', data); }; const onSubmit2 = (data) => { console.log('内层校验提交', data); }; // -------------- 方案1:平级表单写法(推荐) -------------- <div> <form onSubmit={handleSubmit(onSubmit)}> <Controller as={InputMask} control={control} mask="+\9\98 99 999 99 99" name="phone" id="phone" defaultValue={phone} rules={{ required: true }} /> <button type="submit">Send</button> </form> {/* 内层校验表单和主表单平级,用CSS调整到目标视觉位置即可 */} <form onSubmit={handleSubmit2(onSubmit2)}> <Controller as={InputMask} control={control2} mask="+\9\98 99 999 99 99" name="phone_alif" id="phone_alif" rules={{ required: true }} /> <button type="submit">Check</button> </form> </div> // -------------- 方案2:必须视觉嵌套时的写法 -------------- <form onSubmit={handleSubmit(onSubmit)}> <Controller as={InputMask} control={control} mask="+\9\98 99 999 99 99" name="phone" id="phone" defaultValue={phone} rules={{ required: true }} /> {/* 内层不再套form标签 */} <div> <Controller as={InputMask} control={control2} mask="+\9\98 99 999 99 99" name="phone_alif" id="phone_alif" rules={{ required: true }} /> <button type="button" onClick={(e) => { e.stopPropagation(); handleSubmit2(onSubmit2)(); }} > Check </button> </div> <button type="submit">Send</button> </form>
内容的提问来源于stack exchange,提问作者Saidmalik Allayarov
相关产品推荐
相关产品推荐

