Working with Forms & User InputEntry 6 of 10
Controlled vs Uncontrolled: Choosing an Approach
Controlled inputs store values in React state; uncontrolled inputs leave them in the DOM and read them on submit.
Notes
Your earlier notes called FormData "less common, for edge cases." That's outdated: React 19's form actions (next topic) are built on uncontrolled inputs and FormData, and React's docs now present them as the default for submitting forms. Controlled state is still the right choice when the UI must react while the user types.
| Need | Controlled (useState) | Uncontrolled (FormData / refs) |
|---|---|---|
| Value on every keystroke | ✅ | ❌ (read on submit) |
| Live validation, formatting, dependent fields | ✅ | 🟡 Possible with onChange on the form |
| Boilerplate | 🟡 State + handler | ✅ Just name attributes |
| Re-renders while typing | Every keystroke | None |
| Validation on submit | ✅ | ✅ |
| File uploads | 🟡 Store File objects in state | ✅ Built in |
| Multi-select / checkbox groups | ✅ Array state | ✅ getAll() |
| Reset | Reset state | form.reset() |
| React 19 form actions | Works, but not needed | ✅ Designed for it |
Rule of thumb: start uncontrolled; switch a field to controlled when the UI needs its value before submit.
Form libraries:
- React Hook Form is the most used library today. It's uncontrolled under the hood, so it stays fast with large forms.
- Formik, mentioned in your notes, is rarely chosen for new projects now; it's controlled and much less actively maintained.
What / Why / When
- What
Two ways to own form state.
- Why
The right choice removes boilerplate or enables live feedback.
- When
Decide per form, or per field.
Angular
Angular's equivalent choice is between its two built-in form APIs:
| Aspect | Template-driven (FormsModule, ngModel) | Reactive (ReactiveFormsModule, FormGroup) |
|---|---|---|
| Model defined in | Template | Component class |
| Validation | Directives in the template | Functions in the class |
| Dynamic fields | Harder | FormArray, addControl() |
| Testing | Needs the template | Plain class tests |
| Best for | Small, simple forms | Most real forms |
Angular 21 also introduced Signal Forms (form() from @angular/forms/signals), a signal-based form model. It's still experimental, so this reference uses Reactive Forms.
Quick reference
| React | Angular |
|---|---|
Controlled (useState) | Reactive Forms (model in class) |
Uncontrolled (FormData) | Template-driven ngModel / plain DOM |
| React Hook Form | Built-in Reactive Forms |