如何基于useForm在文件上传时临时禁用表单提交?
实现方案
核心思路是通过一个状态变量跟踪文件上传状态,结合React Hook Form的Controller组件和提交按钮的禁用逻辑来实现需求,具体步骤和代码如下:
1. 初始化核心状态与表单实例
用useState创建isUploading状态标记上传中状态,同时初始化useForm实例获取表单管控能力。
2. 用Controller接入自定义文件上传组件
通过Controller将自定义文件上传组件纳入表单管控体系,在文件选择后的上传流程中更新isUploading状态。
3. 绑定提交按钮禁用逻辑
提交按钮的disabled属性关联isUploading状态,同时可搭配formState.isValid确保表单验证通过后才能提交(按需调整)。
完整代码示例
import { useState } from 'react'; import { useForm, Controller, register } from 'react-hook-form'; // 自定义文件上传组件 const CustomFileUpload = ({ onChange, setUploadStatus }) => { const handleFileSelect = async (e) => { const selectedFile = e.target.files[0]; if (!selectedFile) return; // 同步文件信息到表单state onChange(selectedFile); // 开始上传,标记状态 setUploadStatus(true); try { // 替换为你的真实文件上传API await new Promise(resolve => setTimeout(resolve, 2000)); console.log('文件上传成功'); } catch (err) { console.error('文件上传失败', err); } finally { // 无论成败,结束上传状态 setUploadStatus(false); } }; return ( <input type="file" onChange={handleFileSelect} disabled={isUploading} // 上传中禁用选择框,可选 /> ); }; // 主表单组件 const AppForm = () => { const { control, handleSubmit, formState: { isValid } } = useForm({ mode: 'onChange', defaultValues: { file: null, name: '' } }); const [isUploading, setIsUploading] = useState(false); const submitForm = (formData) => { console.log('表单提交数据:', formData); // 你的表单提交逻辑 }; return ( <form onSubmit={handleSubmit(submitForm)}> {/* 普通表单字段示例 */} <div> <label>姓名:</label> <input type="text" {...register('name', { required: '姓名不能为空' })} /> </div> {/* 受控的自定义文件上传字段 */} <div> <label>可选文件上传:</label> <Controller name="file" control={control} render={({ field: { onChange } }) => ( <CustomFileUpload onChange={onChange} setUploadStatus={setIsUploading} /> )} /> </div> {/* 提交按钮:上传中或表单无效时禁用 */} <button type="submit" disabled={isUploading || !isValid} > {isUploading ? '上传中...' : '提交表单'} </button> </form> ); }; export default AppForm;
关键细节说明
isUploading状态在上传开始时设为true,上传完成(成功/失败)后重置为false,确保提交按钮能及时恢复可用状态。- 自定义上传组件中可选择禁用文件选择框,避免用户在上传中重复选择文件。
- 提交按钮的禁用逻辑结合了上传状态和表单验证状态,既满足上传时不能提交的需求,也保证表单本身合法才能提交(按需启用)。
- 实际项目中只需把示例里的模拟上传逻辑替换为真实的后端上传接口即可。
内容的提问来源于stack exchange,提问作者Tomas Randus
相关产品推荐
相关产品推荐

