React Hook Form setValue设置多文件输入框值报错问题
问题根因
这个报错是浏览器原生安全限制导致,和React Hook Form(以下简称RHF)本身逻辑无关:
- 出于防止恶意脚本未经用户授权私自读取、上传本地文件的安全规则,所有
<input type="file">元素的value属性,仅允许被程序设置为空字符串,不能直接赋值为File对象、FileList或者自定义数组。 - 单文件场景下setValue未触发报错,是因为RHF识别到传入值为单个File实例时,不会尝试直接将值写入原生input的
value属性;传入数组类型的多文件值时,RHF的默认字段注册逻辑会尝试将值同步到DOM属性,直接触发浏览器的安全拦截抛出错误。
解决方案
核心原则是:不要让RHF将表单状态中存储的File/File数组,同步写入原生file类型input的value属性,提供两种可直接落地的实现方式:
方案1:调整register配置,关闭原生值同步
给多文件输入框注册时增加特殊配置,阻断RHF向原生DOM赋值的逻辑,不影响正常的表单校验、状态收集:
// 多文件输入框注册配置 <input type="file" multiple {...register('multiple', { value: undefined, // 关键配置:禁止RHF主动给input.value赋值 })} />
对应赋值逻辑补充配置项,确保表单状态正常更新:
const handleMultiple = (files, data) => { setValue('multiple', [...files], { shouldDirty: true, shouldTouch: true, shouldValidate: true }); };
单文件字段如果后续出现同类报错,也可以套用相同配置处理。
方案2:用Controller托管字段(推荐,适配自定义上传组件)
如果使用封装过的自定义上传组件,或者需要更灵活的值控制,直接用RHF提供的Controller组件托管字段,完全跳过默认的原生input注册逻辑,从根源避免DOM赋值操作:
import { Controller, useForm } from 'react-hook-form'; // 表单中多文件字段渲染部分 <Controller name="multiple" control={control} defaultValue={[]} render={({ field }) => ( <input type="file" multiple // 仅绑定事件,不将field.value绑定到input的value属性 onChange={(e) => { const selectedFiles = e.target.files; field.onChange(selectedFiles ? [...selectedFiles] : []); }} onBlur={field.onBlur} /> )} />
这种方式下multiple字段的表单值始终是你需要的File对象数组,不会触发任何原生安全报错,也兼容后续的校验、提交逻辑。
内容的提问来源于stack exchange,提问作者Vahe
相关产品推荐
相关产品推荐

