Module 6.1: Controlled vs Uncontrolled Components

🎯 Learning Objectives
By the end of this lesson, you’ll have a solid grasp of:
- The Essence of Forms in React: The core differences between React managing your form data versus the DOM handling it.
- Controlled Components: Understanding the “React as Single Source of Truth” paradigm.
- Uncontrolled Components: Leveraging
useRefto directly access values from the DOM. - When to Use Which: Weighing the pros, cons, and real-world scenarios for each approach.
1. Controlled Components (React is in Charge)
In this model, the value of an input element is entirely managed by React’s state. Any modification to the input triggers an onChange handler, which then updates the state.

1.1. Data Flow
- The user types a character.
- The
onChangeevent fires. setStateis called to update the new state.- React re-renders the component with the updated value.
- The input displays the value from the state.
1.2. Code Example
import { useState } from 'react';
export default function ControlledForm() {
const [name, setName] = useState<string>('');
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
// React maintains control over every character input.
const value = e.target.value.toLowerCase(); // Example: Always convert to lowercase.
setName(value);
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
alert(`Submit: ${name}`);
};
return (
<form onSubmit={handleSubmit} className="p-4 border rounded">
<h3>Controlled Input</h3>
<input
type="text"
value={name} // 1. Value sourced from state.
onChange={handleChange} // 2. Updated via the handler function.
className="border p-2 rounded"
/>
<p>Current State: {name}</p>
</form>
);
}Pros:
- You get immediate control over data as it’s typed (enabling validation and formatting).
- Easily disable the Submit button if the form isn’t valid.
- Keeps data in sync with other UI elements.
Cons:
- The component re-renders with every keystroke, which might impact performance if the form is very complex.
2. Uncontrolled Components (DOM is in Charge)
Here, the data lives directly within the browser’s DOM node, just like in traditional HTML. React only accesses the value when needed (e.g., on form submission) using a ref.

2.1. Data Flow
- The user types a character -> the input displays it immediately (browser default behavior).
- React does not re-render.
- When required (like on Submit), you fetch the value using
ref.current.value.
2.2. Code Example
import { useRef } from 'react';
export default function UncontrolledForm() {
const nameRef = useRef<HTMLInputElement>(null); // Create a ref typed for HTMLInputElement.
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
// Retrieve the value directly from the DOM.
if (nameRef.current) {
const value = nameRef.current.value;
alert(`Submit: ${value}`);
}
};
return (
<form onSubmit={handleSubmit} className="p-4 border rounded mt-4">
<h3>Uncontrolled Input</h3>
<input
type="text"
ref={nameRef} // Attach the ref here.
defaultValue="Default Value" // Use defaultValue instead of value.
className="border p-2 rounded"
/>
<button type="submit" className="ml-2 bg-blue-500 text-white p-2 rounded">
Submit
</button>
</form>
);
}Pros:
- Generally better performance (no re-renders on typing).
- Easier integration with non-React code (like jQuery or third-party libraries).
Cons:
- Real-time validation (e.g., showing an error as soon as a user types incorrectly) is more difficult.
- Limited control over input formatting.
3. Hands-On Labs
Lab 1: Real-time Password Strength (Controlled)
Build a password input form that dynamically displays a strength meter.
- Features:
- A password input with an “eye icon” to toggle visibility.
- A progress bar that changes color (Red/Yellow/Green) based on the password’s complexity.
- A list of password requirements (uppercase, number, special character).
- Techniques: Controlled Components, Regex Validation.

💡 Hint:
- Use a
passwordstatevariable to store the input value.- Employ a
requirementsarrayof booleans to check against regex patterns every time the password changes.- The UI will involve an input group with a button to toggle the input’s
typebetween"text"and"password".
Lab 2: Drag & Drop File Uploader (Uncontrolled)
Create a slick drag-and-drop file uploader that replaces the default, clunky file input.
- Features:
- Allow users to drag and drop files into a designated area or click to select.
- Display an immediate image preview after a file is dropped.
- Include a “Remove” button to clear the selected file.
- Techniques: Uncontrolled Components (
useReffor the hidden file input), Drag Events (onDragOver,onDrop).

💡 Hint:
- The
type="file"input should be hidden usingdisplay: none.- Use
useRefto programmatically trigger a click on the hidden input when the user interacts with the drop zone.- Listen for
onDropevents, grab the files frome.dataTransfer.files, and display previews usingURL.createObjectURL.
4. Summary
| Characteristic | Controlled | Uncontrolled |
|---|---|---|
| Source of Data | React state | DOM |
| Updates | Re-renders on each keystroke | No re-renders |
| Validation | Real-time (immediate) | On submit |
| Use Cases | Most modern forms, complex validation | Simple forms, File Inputs, extreme performance needs |
Recommendation: Prioritize Controlled Components (in about 90% of cases) to harness React’s full power. Switch to Uncontrolled only when facing significant performance bottlenecks or when integrating with File Inputs or legacy code.