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

React-Hook-Form刷新后文件输入加载失败,提交时文件重置问题求助

解决React Hook Form文件字段从sessionStorage加载后提交校验失败的问题

问题根源

原生<input type="file">受浏览器安全限制,无法通过代码直接设置其选中的文件(包括通过React Hook Form的defaultValues传入File对象)。你之前的写法里,虽然把dataURL转成了File对象并设为默认值,但真实的文件输入框并没有绑定这个文件,提交时表单会读取输入框的真实值(空FileList),导致必填校验不通过。

解决方案

通过自定义标记+校验逻辑绕过原生限制,同时保留sessionStorage的持久化效果:

  1. 调整useForm初始化逻辑
    去掉异步defaultValues里的文件处理,改用标记位判断是否有保存的图片,初始化时给文件字段设一个占位值避免校验失败:

    const getInfoFormData = JSON.parse(sessionStorage.getItem('infoFormData'));
    const hasSavedImg = !!getInfoFormData?.img;
    
    const { register, handleSubmit, formState: { errors, isValid }, setValue, getValues } = useForm({
      mode: 'all',
      defaultValues: {
        firstName: getInfoFormData?.firstName || '',
        lastName: getInfoFormData?.lastName || '',
        aboutMe: getInfoFormData?.aboutMe || '',
        email: getInfoFormData?.email || '',
        mobile: getInfoFormData?.mobile || ''
      }
    });
    
    // 初始化时标记已保存的图片
    useEffect(() => {
      if (hasSavedImg) {
        setValue('img', 'saved');
      }
    }, [hasSavedImg, setValue]);
    
  2. 修改文件输入的校验规则
    自定义校验逻辑,允许占位值'saved'通过校验:

    <input
      type='file' 
      id='upload' 
      onChange={(event) => getImgValueFromInput(event)} 
      {...register('img', {
        required: 'ატვირთეთ ფოტო',
        validate: (value) => {
          // 允许保存标记或真实选中的文件
          return value === 'saved' || (value instanceof FileList && value.length > 0);
        }
      })}
    />
    
  3. 更新文件选择逻辑
    选中新文件时,将其转成dataURL保存到sessionStorage,并更新表单值为真实的FileList:

    const getImgValueFromInput = (event) => {
      const file = event.target.files[0];
      if (!file) return;
    
      const reader = new FileReader();
      reader.onload = (e) => {
        const formData = {
          ...getValues(),
          img: e.target.result
        };
        sessionStorage.setItem('infoFormData', JSON.stringify(formData));
        setValue('img', event.target.files);
      };
      reader.readAsDataURL(file);
    };
    
  4. 提交时处理文件数据
    根据表单值判断是使用保存的dataURL还是新上传的文件:

    const onSubmit = async (data) => {
      let submitImg;
      if (data.img === 'saved') {
        // 把保存的dataURL转回File对象
        submitImg = await dataURLtoFile(getInfoFormData.img, 'avatar.png');
      } else {
        submitImg = data.img[0];
      }
    
      const finalSubmitData = {
        ...data,
        img: submitImg
      };
      // 执行你的提交逻辑
    };
    
  5. 优化展示(可选)
    显示已保存的图片预览,并修改按钮文案:

    <div className='info-img'>
      <label className={errors.img?.message ? 'error' : ' '}>პირადი ფოტოს ატვირთვა</label>
      {hasSavedImg && (
        <img src={getInfoFormData.img} alt="პირადი ფოტო" className="preview" />
      )}
      <label className='input' htmlFor='upload'>
        {hasSavedImg ? 'შეცვალე ფოტო' : 'ატვირთვა'}
      </label>
      {/* 文件输入框 */}
    </div>
    

内容的提问来源于stack exchange,提问作者Killa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 09:05:39