Troubleshooting
Find your symptom on this page. Each entry gives the cause and a link to the section that explains the rule.
onSubmit is not called
The schema rejects the input, often in a hidden field that keeps its value, so
Form, Please does not call onSubmit. See onSubmit receives four
values and Hidden fields keep
their values.
TypeScript rejects a path or control
A field path must exist in the schema input, and the control value type must match the value at that path. See Field paths and Control types.
This program has both errors. emial is not a schema input path. The text
control does not accept the boolean value of newsletter.
// Both errors below are intentional. TypeScript catches them
// before the form ever reaches a browser.
import type { } from "form-please"
import { as } from "form-please/preset-native"
import { } from "react"
import { } from "zod"
const = .({
: .().(2, "Enter at least two characters"),
: .().("Enter a valid email"),
: .(),
})
const = .(, () => [
.("name", { : "text", : "Name", : true }),
.("emial", { : "text", : "Email", : true }), .("newsletter", { : "text", : "Product news" }),])
export function () {
const [, ] = <<typeof >>()
const = .(, {
: {
: "Ada Lovelace",
: "ada@example.com",
: true,
},
: ({ }) => (),
})
let = "Submit to see output"
if ( !== ) = .(, null, 2)
return (
<>
<. ={}>
<.>Create account</.>
</.>
<>{}</>
</>
)
}The transformed value is missing
React Hook Form (RHF) state and the input argument hold the schema input. Only
the value argument of onSubmit holds the transformed output. See The schema
parses once on submit.
Middleware or history skips a change
Direct form.api mutations, such as setValue, bypass middleware and history.
Use form.update(recipe) to make a managed update. See Know which changes
enter middleware and Know
what history records.
delayError does not delay errors after a managed update
A managed update validates through one RHF trigger call, and this call does
not keep the delayError timing. See Understand form state and
validation.
Default values load too late
kit.useForm reads the synchronous defaultValues only once for each mount.
Load the data first, and then mount the form component. See Load an edit-form
baseline and useForm.
kit.useForm requires a definition from this exact form kit
kit.useForm accepts only a definition that the same kit instance created.
The hook keeps its first definition for the complete mount. See Definition
lifetime.
If this error appears after a hot reload, the cause can be the development
server. A hot reload can create a new kit instance and keep the hook state of a
mounted component. The mounted component then holds a definition from the
previous kit. Reload the page, or give the component that calls kit.useForm a
new key to remount it. A remount discards the unsaved values of that form.
If the error appears without a hot reload, import the definition and the kit
from the same module. Two calls to createFormKit create two different kits.