React Hook Form
Use the hook with register, Controller, Zod and ViraStack Mask in one form.
React Hook Form stays the single source of truth. The hook only adds props to the input; it never holds the form value.
register()
const { inputProps, btnProps, rule } = useViraPassword({ policy, value: password })
// inputProps holds attributes only: spread it before or after register()
<input {...inputProps} {...form.register("password", rule)} />
<button {...btnProps} />useWatch()
reset() and setValue() change the input without an input event. Pass value so strength and matches follow them. useWatch also works with the React Compiler, unlike watch().
const password = useWatch({ control: form.control, name: "password" })
const { inputProps, strength } = useViraPassword({ policy, value: password })rule & deps
rule returns the first error key. deps re-validates the confirm field when the password changes.
form.register("password", { ...rule, deps: ["confirm"] })
// deps only runs on user input. After setValue, check the confirm field yourself:
form.setValue("password", next)
form.trigger("confirm")Give the form method="post". Before hydration a form submits natively, and the default GET puts the password in the URL.
Controller
<Controller
control={form.control}
name="password"
render={({ field }) => <PasswordField field={field} />}
/>
function PasswordField({ field }: { field: ControllerRenderProps<Values, "password"> }) {
const { inputProps } = useViraPassword({
policy,
value: field.value,
inputProps: { ...field, onChange: (e) => field.onChange(e.target.value) },
})
return <input {...inputProps} />
}Zod resolver
With a resolver, register rules don't run. Put the same policy into the Zod schema with evaluate:
With Mask
ViraStack Mask v2 also keeps the value in React Hook Form, so both share one useForm. Use them on different inputs, never on the same one.
