Controlled vs Uncontrolled Components
Controlled vs Uncontrolled Components
In React, form inputs (like <input>, <select>, and <textarea>) can be handled in two different ways: as controlled or uncontrolled components.
Controlled Components
In HTML, form elements inherently maintain their own state and update it based on user input. In React, you can bring that state into your component by making React the “single source of truth”.
A controlled component is one where the input’s value is driven entirely by React state.
import { useState } from 'react';
function ControlledForm() {
const [name, setName] = useState('');
const handleChange = (e) => {
// Update React state whenever the input changes
setName(e.target.value);
};
const handleSubmit = (e) => {
e.preventDefault();
console.log('Submitting Name:', name);
};
return (
<form onSubmit={handleSubmit}>
{/* The input value is STRICTLY bound to the React state */}
<input type="text" value={name} onChange={handleChange} />
<button type="submit">Submit</button>
</form>
);
}
Pros of Controlled Components:
- You can easily perform instant input validation as the user types.
- You can conditionally disable submission buttons based on the input.
- You can enforce input formats (e.g., forcing uppercase).
- You can easily pass the data to other UI elements.
Uncontrolled Components
An uncontrolled component leaves the state management up to the DOM. Instead of binding the value to React state and providing an onChange handler, you use a ref (via useRef) to get the form values from the DOM only when you actually need them (like when the form is submitted).
import { useRef } from 'react';
function UncontrolledForm() {
const nameRef = useRef(null);
const handleSubmit = (e) => {
e.preventDefault();
// Read the value directly from the DOM node only on submit
console.log('Submitting Name:', nameRef.current.value);
};
return (
<form onSubmit={handleSubmit}>
{/* No 'value' or 'onChange' prop! */}
<input type="text" ref={nameRef} defaultValue="John" />
<button type="submit">Submit</button>
</form>
);
}
Pros of Uncontrolled Components:
- Less code to write for simple forms.
- Doesn’t trigger a re-render on every single keystroke.
- Easier to integrate with non-React code or legacy codebases.
Which should you use?
In modern React, Controlled Components are widely considered the standard and best practice for building forms, despite being slightly more verbose. They provide vastly more power and predictability, allowing you to create dynamic, highly interactive UIs.
You should only use Uncontrolled Components for very simple forms where performance is a critical concern (e.g., a massive form where typing lags due to re-renders, although this can usually be solved by splitting components) or when integrating with vanilla JavaScript libraries.
Interview Questions
Q: When would you purposefully choose an uncontrolled component over a controlled one?
A: Uncontrolled components are necessary for <input type="file"> (since its value is read-only and cannot be controlled by React). They are also useful when integrating React with third-party, non-React DOM libraries (like vanilla JS charts or Maps) that expect to manage their own internal DOM state.