React-hook-form上传文件未点提交却触发handleSubmit问题
问题描述
使用React-hook-form开发用户注册表单,表单包含多个文件上传项及文本输入字段。选择上传文件时,未点击表单的Submit按钮,SignUp.tsx中的onSubmit函数就被触发(控制台已打印相关日志),且文件已被加入请求payload。
原因分析
问题出在DocUpload.tsx中的上传按钮:<button>元素在表单内默认的type为submit,点击该按钮时会自动触发所在表单的submit事件,进而调用onSubmit函数。
解决方案
1. 修复上传按钮的类型
给DocUpload.tsx中的上传按钮添加type="button",阻止其默认触发表单提交的行为:
// DocUpload.tsx 中修改按钮部分 <button type="button" className="bg-blue-500 text-white px-4 py-2 rounded" onClick={onUpload}> {uploadButtonLabel} </button>
2. 优化文件上传与React-hook-form的集成(可选)
当前代码通过独立useState管理文件,可改用React-hook-form的Controller接管文件上传,更贴合库的设计逻辑,同时减少额外状态维护:
修改DocUpload.tsx:
import { useFormContext, Controller } from 'react-hook-form'; import { useRef, useState, ChangeEvent } from "react"; interface DocUploadProps { name: string; label: string; } export default function DocUpload({ name, label }: DocUploadProps) { const { control } = useFormContext(); const hiddenInputRef = useRef<HTMLInputElement>(null); const [file, setFile] = useState<File | null>(null); const uploadButtonLabel = file ? `Change ${label}` : label; return ( <Controller name={name} control={control} render={({ field: { onChange } }) => { const handleFileChange = (event: ChangeEvent<HTMLInputElement>) => { const newFile = event.currentTarget.files?.[0] || null; onChange(newFile); setFile(newFile); }; const onRemoveFile = () => { onChange(null); setFile(null); }; return ( <div> <input type="file" className="hidden" ref={hiddenInputRef} onChange={handleFileChange} /> <button type="button" className="bg-blue-500 text-white px-4 py-2 rounded" onClick={() => hiddenInputRef.current?.click()}> {uploadButtonLabel} </button> {file && ( <> <span className="ml-2 cursor-pointer text-blue-500 underline" onClick={() => window.open(URL.createObjectURL(file), "_blank")}> View </span> <span className="ml-2 cursor-pointer text-red-500 underline" onClick={onRemoveFile}> Remove </span> </> )} </div> ); }} /> ); };
同时修改SignUp.tsx,移除手动维护的selectedFiles状态,直接在onSubmit中获取文件:
// SignUp.tsx 简化后的代码 export default function DriverSignUp() { const methods = useForm(); const { handleSubmit } = methods; const onSubmit = (data: any) => { console.log(data); // 文件将直接包含在data中 }; return ( <FormProvider methods={ methods } onSubmit={ handleSubmit(onSubmit) } className = "grid grid-cols-10 gap-4" > <div className="col-span-6 p-4" > <RHFInput name="homeAddress" type="text" /> </div> <div className="col-span-4 p-4"> <h2 className="text-2xl font-bold mb-4">Documents</h2> <div className="mb-4 flex flex-col gap-2"> {Documents.map((doc) => ( <DocUpload key={doc.name} name={doc.name} label={doc.label} /> ))} </div> <button type="submit" className="bg-blue-500 text-white px-4 py-2 rounded"> Submit </button> </div> </FormProvider> ); };
总结
核心问题是按钮默认类型导致的表单误提交,添加type="button"即可快速解决。若希望更贴合React-hook-form的使用规范,改用Controller管理文件上传能进一步简化代码逻辑。
内容的提问来源于stack exchange,提问作者sohdata
相关产品推荐
相关产品推荐

