shadcn/ui Dialog与Form组件:handleOpenChange先于onSubmit触发问题求助
解决shadcn/ui Dialog与react-hook-form提交时表单提前重置的问题
问题原因:这是组件的预期行为
shadcn/ui的DialogClose组件核心逻辑就是触发Dialog的关闭(调用onOpenChange并传入false),无论它包裹的按钮是什么类型。点击被DialogClose包裹的Submit按钮时,事件触发顺序是:
DialogClose的点击事件先执行,调用handleOpenChange(false)handleOpenChange里执行form.reset()重置表单- 表单的
onSubmit才触发,但此时表单数据已被清空
解决方案
核心思路是拆分提交与关闭逻辑,让表单提交完成后再处理弹窗关闭和表单重置,而非通过DialogClose直接绑定提交按钮。
修改后的代码示例
const form = useForm<z.infer<typeof formSchema>>({ resolver: zodResolver(formSchema), defaultValues: { name: 'Figma', category: 'Software', version: '1.0', location: 'Taipei', status: 'Available', }, }); const onSubmit = (values: z.infer<typeof formSchema>) => { // 优先完成表单提交逻辑 const newItems = { ...values }; setItems((prevItems) => [...prevItems, newItems]); // 提交成功后手动关闭弹窗并重置表单 setIsOpen(false); form.reset(); }; const handleOpenChange = (open) => { setIsOpen(open); // 仅在非提交状态下关闭弹窗时重置表单 if (!open && !form.formState.isSubmitting) { form.reset(); } }; return ( <Dialog open={isOpen} onOpenChange={handleOpenChange}> <DialogContent> <Form {...form}> <form onSubmit={form.handleSubmit(onSubmit)}> <input type="text" {...form.register("exampleFieldName")} /> {/* 提交按钮不再用DialogClose包裹 */} <Button type="submit">Submit</Button> {/* 关闭按钮保留DialogClose逻辑 */} <DialogClose asChild> <Button type="button" variant="secondary"> Close </Button> </DialogClose> </form> </Form> </DialogContent> </Dialog> )
关键改动说明
- 提交按钮:移除
DialogClose包裹,改为在onSubmit函数末尾手动关闭弹窗并重置表单,确保提交逻辑优先执行。 - 关闭按钮:保留
DialogClose,同时在handleOpenChange中增加form.formState.isSubmitting判断,避免提交过程中误触发表单重置。
内容的提问来源于stack exchange,提问作者wyc
相关产品推荐
相关产品推荐

