使用 react-hook-form 和 Yup 验证子输入类型文件
Validating a child input type file with react-hook-form and Yup
我正在 react-hook-form
和 Yup
的帮助下创建一个带有文件上传的表单。我正在尝试在我的子组件中使用 register 方法。当将 register 作为 prop 传递时(在花括号中解构),验证和提交不起作用。您可以随时提交表单,提交的文件对象为空。
这是一个沙盒 link.
你的代码有几个问题。
1- register
方法 returns 具有以下属性的对象:
{
onChange: function(){},
onBlur:function{},
ref: function(){}
}
当您这样定义输入时:
<input
{...register('photo')}
...
onChange={(event) => /*something*/}
/>
实际上您正在覆盖从 register
方法返回的 onChange
方法,并且 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)
}}
/>
);
}
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 是您文件的完整编辑版本。
我正在 react-hook-form
和 Yup
的帮助下创建一个带有文件上传的表单。我正在尝试在我的子组件中使用 register 方法。当将 register 作为 prop 传递时(在花括号中解构),验证和提交不起作用。您可以随时提交表单,提交的文件对象为空。
这是一个沙盒 link.
你的代码有几个问题。
1- register
方法 returns 具有以下属性的对象:
{
onChange: function(){},
onBlur:function{},
ref: function(){}
}
当您这样定义输入时:
<input
{...register('photo')}
...
onChange={(event) => /*something*/}
/>
实际上您正在覆盖从 register
方法返回的 onChange
方法,并且 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)
}}
/>
);
}
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 是您文件的完整编辑版本。