useSelector/form.Subscribe, ch014). Never read form.state unsubscribed and expect re-renders.undefined.onChangeListenTo/onBlurListenTo + fieldApi.form.getFieldValue (ch013), not just a form-level validator alone.mode="array" + the push/remove/insert/replace/swap/move value methods (ch011). Never reassign field.state.value directly.createFormHook first (ch020), then build every form with useAppForm.revalidateLogic + onDynamic (ch009).useForm behind isLoading (ch010), don't try to update defaultValues reactively after the fact.-start/-nextjs/-remix package (ch002) and follow the createServerValidate + mergeForm pattern (ch022) — don't hand-roll it.| Timing | Field-level sync | Field-level async | Form-level sync | Form-level async |
|---|---|---|---|---|
| Mount | onMount | — | onMount | — |
| Change | onChange | onChangeAsync | onChange | onChangeAsync |
| Blur | onBlur | onBlurAsync | onBlur | onBlurAsync |
| Submit | onSubmit | onSubmitAsync | onSubmit | onSubmitAsync |
Dynamic (needs revalidateLogic) | onDynamic | onDynamicAsync | onDynamic | onDynamicAsync |
| Method | Effect |
|---|---|
pushValue(value) | Append to end |
removeValue(index) | Delete at index |
insertValue(index, value) | Insert at index, shift right |
replaceValue(index, value) | Overwrite at index |
swapValues(a, b) | Exchange two positions |
moveValue(a, b) | Relocate one item |
clearValues() | Empty the array |
| Framework | Form call | Field mechanism |
|---|---|---|
| React / Preact | useForm() | form.Field render prop |
| Vue | useForm() | form.Field scoped slot |
| Solid / Svelte | createForm() | form.Field children fn / snippet |
| Angular | injectForm() | TanStackField directive |
| Lit | new TanStackFormController(this, {...}) | this.#form.field({name}, cb) |
| Symptom | Likely cause | Fix |
|---|---|---|
| "uncontrolled to controlled" warning | field missing from defaultValues | seed every field's default explicitly |
field.state.value is unknown | form type shape too complex | split via FormGroup (ch012) / composition (ch020) |
| "excessively deep type instantiation" | library-internal TS generic depth | not a runtime bug; report upstream |
| cross-field validator looks stale | missing onChangeListenTo/onBlurListenTo | add the listen-to array (ch013) |
| whole form re-renders on any keystroke | reading form.state without a selector | use useSelector/form.Subscribe (ch014) |