Fundamentals
Forms
Master React form handling, covering controlled vs uncontrolled inputs, submission validation, and state synchronization loops.
1. Learning Objectives
In this lesson, you will learn how to capture and validate user inputs using forms in React. By the end of this topic, you will be able to:
- Differentiate between Controlled and Uncontrolled form components.
- Synchronize input fields with local state using
valueandonChange. - Handle form submission events and prevent default browser page reloads.
- Implement form field validation and display inline validation errors.
- Manage complex forms containing multiple input fields.
2. Overview
Handling forms in React differs from vanilla HTML. The recommended pattern is using **Controlled Components**, where the form's input values are driven by React state. This ensures that the React state acts as the "single source of truth" for the form data, making it easy to validate and submit values.
3. Why This Topic Matters
Forms are the primary way users submit data to web applications:
- Real-Time Feedback: Controlled inputs allow you to validate user data as they type (e.g. displaying a warning if an email address is invalid before they hit submit).
- State Synchronization: Syncing inputs with React state makes it easy to enable or disable submit buttons, implement autocomplete dropdowns, and pre-populate fields.
4. Real-World Analogy
Think of controlled inputs like **a bank transaction log**:
- Uncontrolled Input (Cash transaction): You hand money directly to a cashier. The register updates, but you don't have a synchronized ledger tracking it automatically. The DOM holds the value, and you have to query it manually to read it.
- Controlled Input (Digital ledger): You check your bank app before and after a transaction. Every transaction updates the bank's database (state), which then updates your app display (UI) in real-time. The state is the source of truth, and the input field simply displays the current state.
5. Core Concepts
Below is a comparison of Controlled and Uncontrolled components in React:
| Feature | Controlled Components (Recommended) | Uncontrolled Components |
|---|---|---|
| Source of Truth | React state. | The browser DOM. |
| Data Access | Read directly from state variables. | Accessed via DOM references (e.g. useRef). |
| Real-Time Validation | Easy; validation runs on every keystroke. | Difficult; require querying the DOM elements. |
| Value Binding | Uses value={{{state}}} and onChange={{{handler}}}. |
Uses defaultValue or no binding. |
6. Syntax & API Reference
This example shows a standard controlled form in React:
7. Visual Diagram
This diagram displays the synchronization loop inside a controlled input:
8. Live Example — Full Working Code
Below is a complete HTML page demonstrating a signup form with real-time validation:
What just happened? Input fields are bound to the `username` and `password` states. Typing in these inputs updates the state, which then updates the displayed values. When the form is submitted, the submit handler validates the values, displays errors if they are too short, or displays a success message.
9. Interactive Playground
Try It Yourself Challenges:
- Add a checkbox for "Accept Terms of Service" and disable the submit button if the checkbox is unchecked.
- Validate that the username does not contain spaces when the form is submitted.
10. Common Mistakes
| Mistake | Why it happens | Wrong | Correct |
|---|---|---|---|
| Binding input value without an onChange handler | If you bind the value prop to a state variable without an onChange handler, the input becomes read-only and the user cannot type in it. |
<input value={val} /> |
<input value={val} onChange={(e) => setVal(e.target.value)} /> |
| Omitting preventDefault on form submit | Omitting event.preventDefault() allows the browser to reload the page on form submission, losing all local React state. |
const handleSubmit = () => { |
const handleSubmit = (e) => { |
11. Best Practices
- Use controlled components: Bind input values to React state for form inputs.
- Attach onSubmit to the form tag: Trigger form submission via the `` tag's `onSubmit` event, rather than attaching `onClick` listeners to the submit button.
- Keep HTML accessibility tags: Use proper form elements (like ``) to keep forms accessible.
- Reset forms on success: Clear state values after successful submissions to reset form fields.
12. Browser Compatibility/Requirements
React form elements run consistently across all modern web browsers.
13. Interview Questions
Q1: What is the difference between controlled and uncontrolled components in React?
Answer:
- Controlled: The form input's value is driven by React state, which acts as the single source of truth. Changes to the input trigger state updates, which then update the displayed value.
- Uncontrolled: The input's value is managed by the browser DOM. The component reads values from the DOM when needed (like on form submission) using refs (e.g. `useRef`).
Q2: Why is calling `event.preventDefault()` important in form submit handlers?
Answer: By default, browsers trigger a full page reload when a form is submitted. Calling `event.preventDefault()` stops this default behavior. This allows JavaScript to handle form validation and submit data asynchronously (via APIs) without losing the application's local state.
14. Debugging Exercise
Identify why typing in this input field has no effect and the field remains empty:
Diagnosis: The onChange handler is updating the state to the current comment value (which is empty), rather than reading the new input value from the event object.
Fix: Read the new value from event.target.value:
15. Practice Exercises
Exercise 1: Create a password confirmation form
Build a form containing "Password" and "Confirm Password" inputs. Display a red validation warning if the two values do not match during typing or form submission.
16. Scenario-Based Challenge
The Dynamic Checkout Form Address Field Autocomplete:
You are building an address input form. When the user types, the app queries an autocomplete API and displays a list of matching addresses. Clicking a suggestion should populate the form fields. Describe how you would implement this using controlled inputs and event listeners.
17. Quick Quiz
Q1: In a controlled component, what is the source of truth for the input's value?
A) The browser DOM.
B) React state.
C) The value attribute string.
Answer: B — In a controlled component, React state serves as the single source of truth for the input's value.
18. Summary & Key Takeaways
- In controlled components, input values are bound to and managed by React state.
- In uncontrolled components, input values are managed by the browser DOM and accessed via refs.
- Call
event.preventDefault()inside form submissions to prevent full page reloads. - Controlled components simplify form validation and enable real-time UI feedback.
19. Cheat Sheet
| Form Pattern | Purpose |
|---|---|
value={{val}} |
Binds input display to a state variable. |
onChange={(e) => setVal(e.target.value)} |
Syncs input changes with the state variable. |
event.preventDefault() |
Prevents the default browser behavior on form submission. |