You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 11:22:03