Handling Forms in React: Controlled vs. Uncontrolled Components

Forms are a crucial part of any web application, and in React, we primarily handle forms using either controlled or uncontrolled components. Understanding the difference between these two approaches can help you choose the right one for your project. Controlled Components In controlled components, React fully manages the form state. The component's state dictates the form’s values, and any changes are handled via event handlers. Example of a Controlled Input import { useState } from "react"; function ControlledForm() { const [name, setName] = useState(""); const handleChange = (event: React.ChangeEvent) => { setName(event.target.value); }; const handleSubmit = (event: React.FormEvent) => { event.preventDefault(); alert(`Submitted Name: ${name}`); }; return ( Name: Submit ); } Pros of Controlled Components ✅ Easier to validate and manipulate data. ✅ Fully in sync with React’s state. ✅ More predictable behavior. Cons of Controlled Components ❌ Can become verbose for large forms. ❌ Re-renders on every keystroke, potentially affecting performance. Uncontrolled Components Uncontrolled components rely on the DOM itself to manage state. Instead of using React state, we use refs to access form values when needed. Example of an Uncontrolled Input import { useRef } from "react"; function UncontrolledForm() { const inputRef = useRef(null); const handleSubmit = (event: React.FormEvent) => { event.preventDefault(); alert(`Submitted Name: ${inputRef.current?.value}`); }; return ( Name: Submit ); } Pros of Uncontrolled Components ✅ Can be more performant, especially in large forms. ✅ Less re-renders compared to controlled components. ✅ Works well with non-React libraries (e.g., integrating third-party form controls). Cons of Uncontrolled Components ❌ Harder to validate inputs in real-time. ❌ Not in sync with React’s state, making debugging trickier. When to Use Each Approach? Use Case Recommended Approach Simple forms with validation ✅ Controlled Large forms with many fields ✅ Uncontrolled Forms needing real-time updates ✅ Controlled Integrating with third-party UI ✅ Uncontrolled Hybrid Approach: Best of Both Worlds Sometimes, using a mix of both approaches works best! You can initialize inputs using refs (uncontrolled) and then control their state when needed. import { useRef, useState } from "react"; function HybridForm() { const inputRef = useRef(null); const [submittedValue, setSubmittedValue] = useState(""); const handleSubmit = (event: React.FormEvent) => { event.preventDefault(); if (inputRef.current) { setSubmittedValue(inputRef.current.value); } }; return ( Name: Submit {submittedValue && Submitted Name: {submittedValue}} ); } Final Thoughts Controlled components are ideal when you need real-time validation and React-managed state. Uncontrolled components shine in large forms where performance is a concern. A hybrid approach can balance performance and flexibility when needed. Are you using controlled or uncontrolled components in your projects? Let me know your thoughts!

Mar 17, 2025 - 06:15
 0
Handling Forms in React: Controlled vs. Uncontrolled Components

Forms are a crucial part of any web application, and in React, we primarily handle forms using either controlled or uncontrolled components. Understanding the difference between these two approaches can help you choose the right one for your project.

Controlled Components

In controlled components, React fully manages the form state. The component's state dictates the form’s values, and any changes are handled via event handlers.

Example of a Controlled Input

import { useState } from "react";

function ControlledForm() {
  const [name, setName] = useState("");

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setName(event.target.value);
  };

  const handleSubmit = (event: React.FormEvent) => {
    event.preventDefault();
    alert(`Submitted Name: ${name}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Name: <input type="text" value={name} onChange={handleChange} />
      label>
      <button type="submit">Submitbutton>
    form>
  );
}

Pros of Controlled Components

✅ Easier to validate and manipulate data.

✅ Fully in sync with React’s state.

✅ More predictable behavior.

Cons of Controlled Components

❌ Can become verbose for large forms.

❌ Re-renders on every keystroke, potentially affecting performance.

Uncontrolled Components

Uncontrolled components rely on the DOM itself to manage state. Instead of using React state, we use refs to access form values when needed.

Example of an Uncontrolled Input

import { useRef } from "react";

function UncontrolledForm() {
  const inputRef = useRef<HTMLInputElement>(null);

  const handleSubmit = (event: React.FormEvent) => {
    event.preventDefault();
    alert(`Submitted Name: ${inputRef.current?.value}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Name: <input type="text" ref={inputRef} />
      label>
      <button type="submit">Submitbutton>
    form>
  );
}

Pros of Uncontrolled Components

✅ Can be more performant, especially in large forms.

✅ Less re-renders compared to controlled components.

✅ Works well with non-React libraries (e.g., integrating third-party form controls).

Cons of Uncontrolled Components

❌ Harder to validate inputs in real-time.

❌ Not in sync with React’s state, making debugging trickier.

When to Use Each Approach?

Use Case Recommended Approach
Simple forms with validation Controlled
Large forms with many fields Uncontrolled
Forms needing real-time updates Controlled
Integrating with third-party UI Uncontrolled

Hybrid Approach: Best of Both Worlds

Sometimes, using a mix of both approaches works best! You can initialize inputs using refs (uncontrolled) and then control their state when needed.

import { useRef, useState } from "react";

function HybridForm() {
  const inputRef = useRef<HTMLInputElement>(null);
  const [submittedValue, setSubmittedValue] = useState("");

  const handleSubmit = (event: React.FormEvent) => {
    event.preventDefault();
    if (inputRef.current) {
      setSubmittedValue(inputRef.current.value);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Name: <input type="text" ref={inputRef} />
      label>
      <button type="submit">Submitbutton>
      {submittedValue && <p>Submitted Name: {submittedValue}p>}
    form>
  );
}

Final Thoughts

  • Controlled components are ideal when you need real-time validation and React-managed state.
  • Uncontrolled components shine in large forms where performance is a concern.
  • A hybrid approach can balance performance and flexibility when needed.

Are you using controlled or uncontrolled components in your projects? Let me know your thoughts!