Skip to content

Instantly share code, notes, and snippets.

@wpcarro
Created March 29, 2023 17:25
Show Gist options
  • Save wpcarro/6173bf89db6b0ac97db1d7effec721a1 to your computer and use it in GitHub Desktop.
Save wpcarro/6173bf89db6b0ac97db1d7effec721a1 to your computer and use it in GitHub Desktop.
Custom encoder/decoder with react-hook-form and zod.
import React from "react";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import DimensionID from "lib/quality/DimensionID";
////////////////////////////////////////////////////////////////////////////////
// Main
////////////////////////////////////////////////////////////////////////////////
export default function Main() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm({
mode: 'all',
resolver: zodResolver(z.object({
transform: z.string().transform((x, ctx) => {
const parsed = DimensionID.safeParse(x);
if (!parsed.success) {
ctx.addIssue({ code: z.ZodIssueCode.custom });
return z.NEVER;
}
return parsed.data;
}),
refine: z.string().refine(x => DimensionID.safeParse(x).success),
}).strict())
});
return (
<div className="font-mono">
<form onSubmit={handleSubmit((x) => { console.log(x); })}>
<div>
<input type="text" {...register("transform")} />
<span className="text-red-500">{errors?.transform?.message}</span>
</div>
<div>
<input type="text" {...register("refine")} />
<span className="text-red-500">{errors?.refine?.message}</span>
</div>
<button>submit</button>
</form>
</div>
);
}
@wpcarro
Copy link
Author

wpcarro commented Mar 29, 2023

A couple observations:

  • both transform and refine will validate the inputs
  • both transform and refine will model the value as a string (at least according to watch())
  • onSubmit, however, transform will be the fully parsed DimensionID, while refine will still be a string

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment