React Hook Form Zod Typed Resolver
Wire React Hook Form to a Zod resolver so field rules live in one schema, errors arrive per-field, and values stay typed through submit.
Code
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
const SignupSchema = z.object({
email: z.string().email('enter a valid email'),
password: z
.string()
.min(8, 'at least 8 characters')
.regex(/[A-Z]/, 'needs an uppercase letter')
.regex(/\d/, 'needs a digit'),
confirm: z.string(),
}).refine((data) => data.password === data.confirm, {
message: 'passwords do not match',
path: ['confirm'],
});
type SignupValues = z.infer<typeof SignupSchema>;
function SignupForm({ onDone }: { onDone: (values: SignupValues) => void }) {
const {
register,
handleSubmit,
formState: { errors, isSubmitting },
} = useForm<SignupValues>({
resolver: zodResolver(SignupSchema),
defaultValues: { email: '', password: '', confirm: '' },
});
return (
<form onSubmit={handleSubmit(onDone)}>
<input {...register('email')} placeholder="email" />
{errors.email && <p role="alert">{errors.email.message}</p>}
<input {...register('password')} type="password" placeholder="password" />
{errors.password && <p role="alert">{errors.password.message}</p>}
<input {...register('confirm')} type="password" placeholder="confirm" />
{errors.confirm && <p role="alert">{errors.confirm.message}</p>}
<button type="submit" disabled={isSubmitting}>Sign up</button>
</form>
);
}Report a problem with this exampleOpens a pre-filled issue on GitHub.