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

WoX*_*XuS 2 reactjs yup react-functional-component react-hook-form

react-hook-form我正在和的帮助下创建一个带有文件上传的表单Yup。我正在尝试在我的子组件中使用 register 方法。当将寄存器作为道具传递时(在大括号中解构),验证和提交不起作用。您始终可以提交表单,并且提交的文件对象为空。这是一个沙盒链接

Sae*_*loo 6

您的代码存在几个问题。

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

{
  onChange: function(){},
  onBlur:function{},
  ref: function(){}
 }
Run Code Online (Sandbox Code Playgroud)

当您像这样定义输入时:

<input
      {...register('photo')}
      ...
      onChange={(event) => /*something*/}
  />
Run Code Online (Sandbox Code Playgroud)

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

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

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 
            }}
          />
       ...
  );
}
Run Code Online (Sandbox Code Playgroud)

3-由于您的输入类型是这样,因此您的字段file的值具有您可以使用它来处理验证的属性,如下所示:photolength

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)
    }
    )
});
Run Code Online (Sandbox Code Playgroud)

是文件的完整编辑版本。