Technology · React

React Forms Handling

Build and manage controlled forms in React with inputs, validation, and submit handlers.

TL;DR
  1. 01Create controlled inputs by storing value in state.
  2. 02Update state on every keystroke with onChange handlers.
  3. 03Validate and submit forms with a form submit event.

Controlled Inputs

  • Create a controlled input by storing the value in state.
    const [email, setEmail] = useState("");
    <input
      value={email}
      onChange={(e) => setEmail(e.target.value)}
    />
  • The input value stays in sync with the state at all times.
  • React is the single source of truth for the input's value.
  • Every keystroke updates state, which updates the input display.
  • Controlled inputs let you validate and transform input before storing.

Multiple Inputs

  • Store form data in a single state object to keep it organized.
    const [form, setForm] = useState({ name: "", email: "" });
    const handleChange = (e) => {
      const { name, value } = e.target;
      setForm(prev => ({ ...prev, [name]: value }));
    };
  • Use the name attribute to identify which input changed.
  • Spread the previous state and update only the changed field.
  • This pattern scales well as forms grow with more fields.
  • Consider moving to a form library for very large forms.

Checkboxes and Selects

  • For checkboxes, use checked instead of value in state.
    const [agree, setAgree] = useState(false);
    <input
      type="checkbox"
      checked={agree}
      onChange={(e) => setAgree(e.target.checked)}
    />
  • For select dropdowns, store the selected value in state.
    const [role, setRole] = useState("user");
    <select value={role} onChange={(e) => setRole(e.target.value)}>
      <option value="user">User</option>
      <option value="admin">Admin</option>
    </select>
  • Handle radio buttons like checkboxes but with a group of options.
  • Textareas work like text inputs with the value attribute.

Validation

  • Validate input on every change or only when the user leaves the field.
    const [email, setEmail] = useState("");
    const [error, setError] = useState("");
    const handleChange = (e) => {
      const value = e.target.value;
      setEmail(value);
      if (!value.includes("@")) setError("Invalid email");
      else setError("");
    };
  • Show validation errors near the invalid input for quick feedback.
  • Disable the submit button while there are validation errors.
    <button disabled={error}>Submit</button>
  • Use a form library like React Hook Form for complex validation rules.

Form Submission

  • Prevent the default form submission and handle it with JavaScript.
    const handleSubmit = (e) => {
      e.preventDefault();
      console.log(form);
    };
    <form onSubmit={handleSubmit}>
      {/* inputs here */}
      <button type="submit">Submit</button>
    </form>
  • Access form data from state and send it to an API.
  • Show loading and success states while submitting.
  • Reset the form after successful submission using setForm({}).
  • Handle errors gracefully and display them to the user.

Tip: Use the name attribute on inputs to build a generic change handler that works for any number of fields without repetition.

Warning: Always call e.preventDefault() in the submit handler to stop the browser from reloading the page.

React Error BoundariesReact useMemo and useCallback