Skip to content

Instantly share code, notes, and snippets.

@bryanltobing
Created August 12, 2022 04:53
Show Gist options
  • Save bryanltobing/3eecd9915c75d8b406195d5ecbb6644e to your computer and use it in GitHub Desktop.
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
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