Function: useZodForm()
useZodForm<
TSchema>(schema,options?):object
Defined in: packages/react/src/useZodForm.ts:85
React Hook Form integration hook for Zod v4 schemas.
Walks the schema to produce FormField[] and wires useForm with a
zodResolver. When options.optimization is set the zodResolver is
replaced by per-field validation (via schemaLite) and the resolver
import is tree-shaken in production builds.
Type Parameters
TSchema
TSchema extends ZodObject<$ZodLooseShape, $strip>
Parameters
schema
TSchema
The z.object({...}) schema to generate the form from.
options?
UseZodFormOptions<TSchema>
Optional hook configuration.
Returns
{ form, fields } — the RHF UseFormReturn and the FormField[] array.
fields
fields:
FormField[] =walkResult.fields
form
form:
UseFormReturn<output<TSchema>,any,output<TSchema>>
schemaError
schemaError:
string|null=walkResult.error
Non-null when walkSchema threw — lets consumers display the error instead of an empty form
schemaLite
schemaLite:
$ZodType<unknown,unknown,$ZodTypeInternals<unknown,unknown>> |null=walkResult.schemaLite
SchemaLite for submit-time validation (non-null when optimization is enabled and top-level effects exist)
Example
const { form, fields } = useZodForm(loginSchema);
return (
<form onSubmit={form.handleSubmit(onSubmit)}>
{fields.map((f) => <input key={f.key} {...form.register(f.key)} />)}
</form>
);
Use When
- You need direct access to the RHF
forminstance (e.g. to callform.setValue) - You are building a custom renderer on top of
FormField[] - You want to colocate form state management with your own layout logic
Avoid When
- You just need a working form UI — use
<ZodForm>instead;useZodFormreturnsfields[]andform, but rendering those fields requires wiring up each field component yourself
Never
- NEVER pass a new schema object on every render —
walkSchemais memoized by schema identity; an unstable reference causes re-walking on every render cycle; FIX: declare the schema outside the component or wrap inuseMemo - NEVER forget
normalizeFormValues()before manually callingschema.safeParse()— the hook's internal resolver applies normalization, but manual calls do not; FIX: always callschema.safeParse(normalizeFormValues(values)) - NEVER mix
formRegistryandfieldsoptions on the same call — whenformRegistryis provided,fieldsis ignored entirely with no merge and no warning; FIX: pick one or merge field config into the registry manually before passing it