Created
August 12, 2022 04:53
-
-
Save bryanltobing/3eecd9915c75d8b406195d5ecbb6644e to your computer and use it in GitHub Desktop.
zod validation and react hook form for input type file with file preview
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { zodResolver } from "@hookform/resolvers/zod"; | |
import { useMemo } from "react"; | |
import { useForm } from "react-hook-form"; | |
import { z } from "zod"; | |
const getFileUrl = (file?: File) => | |
file ? window.URL.createObjectURL(file) : ""; | |
const FilePage = () => { | |
const schema = z.object({ | |
file: | |
typeof window === "undefined" // this is required if your app rendered in server side, otherwise just remove the ternary condition | |
? z.undefined() | |
: z | |
.instanceof(FileList) | |
.refine(file => file.length !== 0, { | |
message: "File is required", | |
}) | |
.refine( | |
file => { | |
const fileType = file.item?.(0)?.type || ""; | |
return fileType === "image/png"; | |
}, | |
{ | |
message: "File must be in .png format", | |
} | |
) | |
.refine( | |
file => { | |
const fileSize = file.item?.(0)?.size || 0; | |
return fileSize <= 200000; | |
}, | |
{ message: "File size must be less than or equal to 200kb" } | |
), | |
}); | |
const { | |
register, | |
handleSubmit, | |
formState: { errors }, | |
watch, | |
} = useForm<z.infer<typeof schema>>({ | |
resolver: zodResolver(schema), | |
}); | |
const file = watch().file?.item(0) || undefined; | |
const filePreview = useMemo(() => getFileUrl(file), [file]); | |
return ( | |
<div> | |
<h1>Hello StackBlitz!</h1> | |
<p>Start editing to see some magic happen :)</p> | |
<form onSubmit={handleSubmit(data => {})}> | |
<input type="file" {...register("file")} /> | |
<button type="submit">Submit</button> | |
<img src={filePreview} alt="company-logo" /> | |
<div>{errors.file?.message}</div> | |
</form> | |
</div> | |
); | |
}; | |
export default FilePage; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment