Validation

A validator is any function that receives the current values and returns an errors object keyed by field path. Return an empty object when everything is valid.

Try it — flip the mode knob and watch when errors appear:

Live demo
JSX
const form = createForm({
  initialValues: { email: "", age: 0 },
  validator: (values) => {
    const errors = {};
    if (!values.email.includes("@")) errors.email = "Invalid email";
    if (values.age < 18) errors.age = "Must be 18 or older";
    return { errors };
  },
});

Errors surface on form.errors by the same path you registered:

JSX
<input {...form.register("email")} />
{form.errors.email ? <span class="error">{form.errors.email}</span> : null}

Schema validation (Zod)

Wrap a schema in a small resolver that maps issues to the path-keyed shape:

JSX
import { z } from "zod";

const schema = z.object({
  email: z.string().email("Invalid email"),
  age: z.number().min(18, "Must be 18 or older"),
});

const zodResolver = (schema) => (values) => {
  const result = schema.safeParse(values);
  if (result.success) return { errors: {} };
  const errors = {};
  for (const issue of result.error.issues) {
    errors[issue.path.join(".")] = issue.message;
  }
  return { errors };
};

const form = createForm({
  initialValues: { email: "", age: 0 },
  validator: zodResolver(schema),
  mode: "onBlur",
});
Async validators

A validator may return a Promise. While it resolves, form.isValidating is true — useful for server-side uniqueness checks.

When validation runs

The mode option controls the trigger:

modeValidates…
onBlurwhen a field loses focus, and on submit (default).
onChangeon every keystroke, and immediately on mount.
onSubmitonly on submit.

Once a field has an error, reValidateMode ("onChange" default, or "onBlur") controls when it is re-checked as the user fixes it.

JSX
const form = createForm({
  initialValues: { email: "" },
  validator,
  mode: "onChange",
});

handleSubmit always runs the validator first and only calls your handler when isValid is true, so a final check is guaranteed regardless of mode.