Reputation: 145
I'm creating a form with a file upload with help of react-hook-form
and Yup
. I am trying to use the register method in my child component. When passing register as a prop (destructured in curly braces) the validation and submiting doesn't work. You can always submit the form and the submitted file object is empty.
Here's a sandbox link.
Upvotes: 2
Views: 4148
Reputation: 6564
There are several of problems with your code.
1- register
method returns an object with these properties:
{
onChange: function(){},
onBlur:function{},
ref: function(){}
}
when you define your input like this:
<input
{...register('photo')}
...
onChange={(event) => /*something*/}
/>
actually you are overrding the onChange
method which has returned from register
method and react-hook-form couldn't recognize the field change event. The solution to have your own onChange
alongside with react-hook-form
's onChange
could be something like this:
const MyComp = ()=> {
const {onChange, ...registerParams} = register('photo');
...
return (
...
<input
{...params}
...
onChange={(event) => {
// do whatever you want
onChange(event)
}}
/>
);
}
2- When you delete the photo, you are just updating your local state, and you don't update photo
field, so react-hook-form
doesn't realize any change in your local state.
the problems in your ImageOne
component could be solved by change it like this:
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- Since your input type is file
so, the value of your photo
field has length
property that you can use it to handle your validation like this:
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 is the full edited version of your file.
Upvotes: 6