Blog #29: When 'Controlled Component' turns into a performance burden
I used to believe every input in React must be a Controlled Component. Until I had to build a giant form with 100 fields.
I admit I was once a "Control Freak" when writing React. I always believed the "standard React way" was for every input value to be stored in State and passed back to the value attribute of the Input.
I believed it because every tutorial on the internet taught it that way. "Controlled components give you absolute control over data, easy to validate, easy to format (like automatic capitalization)." It sounded perfect. But reality taught me a painful lesson when I participated in building an ERP system with "endless" Forms.
1. Context: When typing is an ordeal
The project had insurance registration forms with nearly 100 fields: Text, Number, Date, Select, Checkbox... Because I believed in the "standard," I wrapped the whole form in a large state object.
The result: Every time the User typed 1 character in the name input, the entire 100-field form re-rendered. On weak office computers, typing was delayed by 2-3 seconds. The User went crazy, and I was stuck.
2. Concept: Controlled vs Uncontrolled
The problem was I forced React to do something that the browser (plain HTML) does ten thousand times better: Managing input state.
// How I used to do it (Sounds "correct" but laggy)
const MyInput = () => {
const [val, setVal] = useState("");
return <input value={val} onChange={(e) => setVal(e.target.value)} />;
};
Why is it bad at large scale? Because every keystroke triggers a cycle: Keystroke -> State changes -> Re-render entire Component -> Update DOM. With 100 inputs reacting simultaneously, the browser's Main thread will be choked.
3. Practical Approach and Balance
A Junior will choose Controlled for everything because it's the first thing learned. They fear ref and consider Uncontrolled something "non-React."
Comparison of two ways:
- The "Library Standard" way: Fully Controlled. Convenient for complex validation logic but a performance disaster for large forms. Clunky code due to too many
onChange. - The Practical way (Uncontrolled / Hybrid):
- Let the browser manage input values itself (using
useReforFormData). - Only use Controlled for fields that truly need an instant reaction (e.g., suggested search).
- Use libraries like
React Hook Form—where they use Uncontrolled to optimize re-renders but still provide an easy-to-use API.
- Let the browser manage input values itself (using
Lesson Learned
I learned that: Loyalty to a theory is not as important as the user's actual experience.
- When the old (Controlled) way is still correct: Small forms (< 10 fields), suggestive search boxes, inputs that need constant formatting (like money with commas).
- When to avoid: Avoid using Controlled for large data forms, Dashboard pages with hundreds of input boxes.
Sometimes, the way to make React run fastest is... don't force it to manage what the browser already does too well.
Notes on the day I learned to let go of control to find smoothness.
Series • Part 29 of 50