API Reference
Complete reference for useForm, components, hooks, HOCs, and utilities
API Reference
Complete reference for everything Formify exports.
useForm(options)
The core hook. Returns the full form bag (see below).
const form = useForm<Values>({
initialValues,
onSubmit,
validate?, // (values) => errors | Promise<errors>
validationSchema?, // config schema | function | yup-like object
validateOnChange?, // default true
validateOnBlur?, // default true
validateOnMount?, // default false
validateOnSubmit?, // default true — set false to skip validation on submit
enableReinitialize?,// default false — reset state when initialValues change
focusFirstError?, // default true — focus the first invalid field on submit
validateDebounce?, // global debounce (ms) for async validation
messages?, // global message overrides, keyed by rule name
plugins?, // FormPlugin[]
onError?, // (errors) => void — called when submit fails validation
});Options
| Option | Type | Default | Description |
|---|---|---|---|
initialValues | Values | — | Initial form values. |
onSubmit | (values, helpers) => void | Promise | — | Called with valid values. Async functions drive isSubmitting. |
validate | (values) => errors | Promise<errors> | — | Form-level validator. |
validationSchema | config | fn | yup-like | — | See validation styles. |
validateOnChange | boolean | true | Validate fields on change. |
validateOnBlur | boolean | true | Validate fields on blur. |
validateOnMount | boolean | false | Run validation once on mount. |
validateOnSubmit | boolean | true | false skips validation entirely on submit. |
enableReinitialize | boolean | false | When initialValues change, reset values/errors/touched. |
focusFirstError | boolean | true | Focus the first invalid [name] field after a failed submit. |
validateDebounce | number | 0 | Global debounce for async validation (per-field options win). |
messages | Record<string, string> | — | Global error messages, e.g. { required: "Füll mich aus" }. |
plugins | FormPlugin[] | — | See plugins. |
onError | (errors) => void | — | Fired when submit fails validation. |
The form bag
useForm returns everything Formik's useFormik returns, plus extras:
State
values,errors,touched,initialValues,isSubmitting,isValidating,submitCount,status,dirty,isValidvalidating(extra: per-field async flags, e.g.form.validating.username)messages(extra: the resolved message dictionary — defaults + overrides)
Handlers
handleChange(event)orhandleChange("field")(eventOrValue)handleBlur(event)orhandleBlur("field")(eventOrTouched)handleSubmit(event?)— prevents default, validates, submitshandleReset()— resets to initial values
Imperative helpers
setFieldValue(field, value, shouldValidate?)setFieldTouched(field, touched?, shouldValidate?)setFieldError(field, error?)setValues(values, shouldValidate?)setErrors(errors)setTouched(touched, shouldValidate?)setStatus(status?)setSubmitting(bool)setFormifyState(state | (prev) => state)resetForm(nextState?)submitForm()— Promise; throws nothing; blocks while submittingvalidateForm()— Promise of the errors objectvalidateField(field)— Promise of the field error (or undefined)
Field accessors
getFieldProps(name)→{ name, value, onChange, onBlur }— spread onto any inputgetFieldMeta(name)→{ value, error, touched, initialValue, isValidating }getFieldHelpers(name)→{ setValue, setTouched, setError }registerField(name, { validate })/unregisterField(name)
Validation styles
// 1. Config schema (recommended) — plain data, zero boilerplate
validationSchema: {
email: { required: true, email: true, minLength: [5, "Too short"] },
}
// 2. Validation function
validate: (values) => {
const errors = {};
if (values.password !== values.confirm) {
errors.confirm = "Passwords do not match";
}
return errors;
}
// 3. Yup-like schema (duck-typed — works without installing yup)
import * as yup from "yup";
validationSchema: yup.object({
email: yup.string().email().required(),
})Components
<Formify>
Render-prop wrapper over useForm:
<Formify initialValues={...} onSubmit={...} validationSchema={...}>
{(form) => <MyForm form={form} />}
</Formify>Also supports render and component props.
<Form>
A <form> pre-wired to the nearest form context. Optional onSubmit override.
<Field>
Binds one field to the context:
<Field name="email" type="email" placeholder="you@example.com" />
<Field name="country" as="select">
<option value="">Select…</option>
<option value="in">India</option>
</Field>
<Field name="bio">
{({ field, meta }) => (
<div>
<textarea {...field} />
{meta.touched && meta.error && <p>{meta.error}</p>}
</div>
)}
</Field>Supports as, component, children (fn), render and validate (field-level validator).
<FastField>
Memoized <Field> for large forms.
<ErrorMessage>
<ErrorMessage name="email" component="p" className="error" />
// or
<ErrorMessage name="email">{(msg) => <span>⚠ {msg}</span>}</ErrorMessage>Only renders when the field is touched and has an error.
<FieldArray>
Helpers for array fields: push, pop, swap, move, insert, remove, replace, unshift, plus form and name.
<FieldArray name="emails">
{({ push, remove, form }) => (
<>
{form.values.emails.map((email, i) => (
<div key={i}>
<Field name={`emails.${i}`} />
<button type="button" onClick={() => remove(i)}>Remove</button>
</div>
))}
<button type="button" onClick={() => push("")}>Add email</button>
</>
)}
</FieldArray>Context
<FormifyProvider value={form}>— provide a bag manually<FormifyConsumer>— render-prop consumeruseFormifyContext()— access the nearest bag
Hooks
useField(propsOrName)
const [field, meta, helpers] = useField("email");
const [field, meta, helpers] = useField({
name: "email",
validate: (value) => (value === "x" ? "No" : undefined),
});
<input {...field} />
{meta.touched && meta.error && <p>{meta.error}</p>}useFormValidator (v1 alias)
Backward-compatible alias — see migration.
HOCs
withFormify(config)(Component)— injectsformifypropconnect(Component)— injectsformifyprop from context
Formatters
Format field values as the user types (onChange) or on blur (onBlur), controlled per field via the format config — see Formatters.
validationSchema: {
ssn: { format: "ssn" }, // 123-45-6789 as you type
ein: { format: "ein" }, // 12-3456789
tin: { format: { type: "tin", options: { mask: "XX-XXXXXXX" } } },
phone: {
format: { type: "phone", options: { country: "US", ext: true } },
phone: true,
},
name: { format: [{ type: "trim", trigger: "onBlur", options: { mode: "both" } }, "upperCase"] },
}Normalization
Normalize values as the user types — see Plugins for the normalize field config:
validationSchema: {
username: { required: true, normalize: "trim" },
code: { normalize: "uppercase" },
phone: { normalize: (v) => String(v).replace(/[^\d+]/g, "") },
}Utilities
getIn, setIn, removeIn, toPath, isEmptyObject, isEmptyValue, isPromise, isObject, isString, isEvent, deepEqual, interpolate, hasErrors, touchAll, validateYupSchema, validateYupSchemaSync, yupToFormErrors, plus formatter helpers (applyMask, trim, ssn, ein, itin, tin, mask, phone, zip, creditCard, currency, date, time, upperCase, lowerCase, digitsOnly) and the registerFormatter / FORMATTERS registry.