React Hook Form编辑场景下提交按钮无法触发onSubmit函数
问题原因分析
编辑场景下点击submit按钮无响应、不触发onSubmit,核心原因是表单验证静默失败:React Hook Form在submit时会自动执行校验,若校验不通过会直接阻止onSubmit执行,但如果错误未正确绑定到FormMessage或未被主动打印,就会出现无报错、无响应的现象。结合你的代码,具体触发点可能有以下几个:
initialData字段类型不符合Zod校验规则
你的formSchema中dailyOrders的id要求是z.string().min(1),如果编辑时initialData.productsData里的id是数字类型(比如数据库返回的Number),Zod会判定校验失败;另外quantity是z.coerce.number().min(1),如果初始值是0或空值,coerce转换后会变成NaN,同样触发校验失败。Select组件绑定存在冗余值
代码中Select同时设置了defaultValue={field.value}和value={field.value},可能导致值绑定冲突,使得productId的初始值未正确同步,触发productId非空校验失败。date字段格式不匹配
Input type="date"要求值为YYYY-MM-DD格式的字符串,如果initialData.date是Date对象或其他格式字符串,会导致date字段校验失败。
解决方案
1. 修正initialData的字段格式与类型
在设置defaultValues时,对编辑场景的数据做类型转换和默认值处理,确保完全符合Zod校验规则:
const defaultValues = initialData ? { date: new Date(initialData.date).toISOString().split('T')[0], // 统一转为YYYY-MM-DD格式 dailyOrders: initialData.productsData.map(item => ({ ...item, id: String(item.id), // 将id强制转为字符串 quantity: item.quantity >= 1 ? item.quantity : 1 // 确保quantity至少为1 })) } : { date: '', dailyOrders: [{ id: '1', productId: '', quantity: 0 }] }
2. 修复Select组件的绑定冗余
去掉Select和SelectValue上的defaultValue,仅保留value和onChange与field绑定,避免值冲突:
<FormField control={form.control} name={`dailyOrders.${index}.productId`} render={({ field }) => { return ( <FormItem> <FormLabel>Product</FormLabel> <Select disabled={loading} onValueChange={field.onChange} value={field.value} > <FormControl> <SelectTrigger> <SelectValue placeholder="Select a product" /> </SelectTrigger> </FormControl> <SelectContent> {products.map((product) => ( <SelectItem key={product.id} value={product.id}> {product.name} </SelectItem> ))} </SelectContent> </Select> <FormMessage /> </FormItem> ) }} />
3. 调试验证状态(可选)
在submit按钮的点击事件中主动打印验证状态,快速定位失败字段:
<Button onClick={() => { console.log('表单是否有效:', form.formState.isValid); console.log('验证错误详情:', form.formState.errors); }} disabled={loading} className="ml-auto" type="submit" > {action} </Button>
4. 强化Quantity字段的输入合法性
在Quantity的Input上添加min属性,从UI层面避免用户输入0或负数:
<Input type="number" {...field} min="1" />
内容的提问来源于stack exchange,提问作者Pawan Rijal

