useFormContext+shadcn弹窗表单:父组件触发保存函数失效问题
问题排查与解决方案
你当前的核心问题是按钮事件绑定逻辑错误,结合react-hook-form的工作机制,以下是具体修复点:
1. 修正按钮的事件绑定方式
react-hook-form的handleSubmit必须绑定在表单的onSubmit属性上,而非按钮的onClick事件。按钮只需设置type="submit"(若在表单外则配合form属性关联表单ID)即可触发提交逻辑。
错误写法:
<button form="product-form" type="submit" onClick={methods.handleSubmit(onSubmit)}>保存</button>
正确写法(按钮在表单内时):
<form id="product-form" onSubmit={methods.handleSubmit(onSubmit)}> {/* 表单项 */} <button type="submit">保存</button> </form>
若按钮必须放在弹窗底部(表单外),只需保证:
- 按钮的
form属性与表单id完全一致 - 表单已绑定
onSubmit={methods.handleSubmit(onSubmit)} - 按钮无需额外绑定
onClick
2. 确保FormProvider完整覆盖表单与按钮
弹窗组件中,FormProvider需要同时包裹表单组件和保存按钮,让两者处于同一form上下文环境:
<FormProvider {...methods}> <ProductSurveyForm /> {/* 弹窗底部操作栏 */} <div className="modal-actions"> <button type="button" onClick={closeModal}>取消</button> <button form="product-form" type="submit">保存</button> </div> </FormProvider>
3. 检查子组件表单的上下文关联
子组件通过useFormContext获取上下文后,需将表单的onSubmit直接绑定到上下文提供的handleSubmit(无需重新定义提交函数):
// ProductSurveyForm.jsx import { useFormContext } from "react-hook-form"; export default function ProductSurveyForm() { const { register, handleSubmit } = useFormContext(); return ( <form id="product-form" onSubmit={handleSubmit}> <input {...register("productTitle", { required: "标题不能为空", maxLength: { value: 50, message: "标题不能超过50字" } })} placeholder="输入产品标题" /> </form> ); }
4. 排查弹窗Portal的影响
若shadcn弹窗使用Portal将内容挂载到body下,按钮与表单可能处于不同DOM分支。可临时将按钮移至表单内部测试,确认是否为Portal导致的表单关联失效。
5. 校验useForm初始化配置
确保父组件中useForm的初始化配置正确,比如设置提交触发模式:
const methods = useForm({ defaultValues: { productTitle: "" }, mode: "onSubmit" // 明确仅在提交时触发校验与提交逻辑 });
内容的提问来源于stack exchange,提问作者Sherlac Alexander
相关产品推荐
相关产品推荐

