使用 react-hook-form 和 Yup 验证子输入类型文件

Validating a child input type file with react-hook-form and Yup

我正在 react-hook-formYup 的帮助下创建一个带有文件上传的表单。我正在尝试在我的子组件中使用 register 方法。当将 register 作为 prop 传递时(在花括号中解构),验证和提交不起作用。您可以随时提交表单,提交的文件对象为空。 这是一个沙盒 link.

你的代码有几个问题。

1- register 方法 returns 具有以下属性的对象:

{
  onChange: function(){},
  onBlur:function{},
  ref: function(){}
 }

当您这样定义输入时:

<input
      {...register('photo')}
      ...
      onChange={(event) => /*something*/}
  />

实际上您正在覆盖从 register 方法返回的 onChange 方法,并且 react-hook-form 无法识别字段更改事件。拥有自己的 onChangereact-hook-formonChange 的解决方案可能是这样的:

const MyComp = ()=> {
  const {onChange, ...registerParams} = register('photo');
  ...
  return (
    ...
    <input
        {...params}
        ...
        onChange={(event) => {
          // do whatever you want
          onChange(event)
        }}
      />
  );
}

2- 当你删除照片时,你只是在更新你的本地状态,你没有更新 photo 字段,所以 react-hook-form 没有意识到你的本地状态有任何变化.

您的 ImageOne 组件中的问题可以通过这样更改来解决:

function ImageOne({ register, errors }) {
  const [selectedImage, setSelectedImage] = useState(null);
  const { onChange, ...params } = register("photo");
  return (
    ...
    <Button
           className="delete"
           onClick={() => {
              setSelectedImage(null);
              //Make react-hook-form aware of changing photo state
              onChange({ target: { name: "photo", value: [] } });
            }}
          >
         ...
          <input
            //name="photo"
            {...params}
            type="file"
            accept="image/*"
            id="single"
            onChange={(event) => {
              setSelectedImage(event.target.files[0]);
              onChange(event); // calling onChange returned from register 
            }}
          />
       ...
  );
}

3- 因为你的输入类型是 file 所以你的 photo 字段的值有 length 属性 你可以用它来处理你的验证这个:

const schema = yup.object().shape({
  photo: yup
    .mixed()
    .test("required", "photo is required", value => value.length > 0)
    .test("fileSize", "File Size is too large", (value) => {
      return value.length && value[0].size <= 5242880;
    })
    .test("fileType", "Unsupported File Format", (value) =>{
      return value.length && ["image/jpeg", "image/png", "image/jpg"].includes(value[0].type)
    }
    )
});

Here 是您文件的完整编辑版本。