Capítulo 14 de 39
handleSubmit(onValid, onInvalid?) returns an event handler that validates first, then calls onValid with typed data (or onInvalid with the error object) — the standard bridge between a <form onSubmit> and RHF's validation.
handleSubmit(onValid)(event)'s promise resolves with whatever onValid returns, instead of discarding it.undefined: to block editing while still submitting a value, use readOnly or disable a wrapping <fieldset> instead of the input itself.onSubmit are not swallowed: wrap async requests in try/catch and call setError("root.serverError", { type, message }) in the catch to surface it — this also sets formState.isSubmitSuccessful to false..transform(), Yup, custom) changes the output shape from the field/input shape, type useForm<FormInput, unknown, FormOutput>() so handleSubmit's callback is typed as the transformed output, not the raw input.const onSubmit: SubmitHandler<FormValues> = (data) => console.log(data)
const onError: SubmitErrorHandler<FormValues> = (errors) => console.log(errors)
<form onSubmit={handleSubmit(onSubmit, onError)}>
const schema = z.object({ emailOrPhone: z.string().trim() })
.transform(({ emailOrPhone }) => ({
isEmail: emailOrPhone.includes("@"),
isPhone: /^\d+$/.test(emailOrPhone),
value: emailOrPhone,
}))
type FormInput = z.input<typeof schema>
type FormOutput = z.output<typeof schema>
const { register, handleSubmit } = useForm<FormInput, unknown, FormOutput>({
resolver: zodResolver(schema),
})
const onSubmit: SubmitHandler<FormOutput> = (data) => { /* data.isEmail, data.isPhone */ }
handleSubmit's callback correctly when a resolver's .transform() changes the output shape.onSubmit throw without a try/catch: handleSubmit doesn't swallow it, but nothing surfaces it to the user either unless you catch it and call setError.undefined — use readOnly or a disabled <fieldset> instead.TTransformedValues generic when using a transforming resolver: the callback gets typed as the raw input shape, producing type errors on the transformed properties.handleSubmit always validates before calling either callback — it's the single entry point for a valid/invalid submit branch.try/catch around your async call, surfaced via setError("root.serverError", ...).useForm<Input, Context, Output>()'s third generic for handleSubmit's callback to type-check against the transformed shape.resolver option and its TTransformedValues generic.<Form> component built around the same validate-then-submit flow.