NelsonLabs
React Fundamentals/Forms in React

Forms in React

Forms in React are controlled through state — unlike regular HTML forms where the DOM manages input values, React forms keep the values in state and sync the DOM to that state.

A complete controlled form
jsx
import { useState } from "react";

function ContactForm() {
  const [form, setForm] = useState({
    name: "",
    email: "",
    message: "",
    course: "html",
  });
  const [status, setStatus] = useState("idle"); // idle | loading | success | error

  // Generic handler — works for any field
  function handleChange(e) {
    const { name, value } = e.target;
    setForm(prev => ({ ...prev, [name]: value }));
  }

  async function handleSubmit(e) {
    e.preventDefault();
    setStatus("loading");

    try {
      const res = await fetch("/api/contact", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(form),
      });
      if (!res.ok) throw new Error("Failed");
      setStatus("success");
      setForm({ name: "", email: "", message: "", course: "html" });
    } catch {
      setStatus("error");
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        name="name"
        value={form.name}
        onChange={handleChange}
        placeholder="Your name"
        required
      />
      <input
        name="email"
        type="email"
        value={form.email}
        onChange={handleChange}
        required
      />
      <select name="course" value={form.course} onChange={handleChange}>
        <option value="html">HTML</option>
        <option value="css">CSS</option>
        <option value="js">JavaScript</option>
      </select>
      <textarea
        name="message"
        value={form.message}
        onChange={handleChange}
        rows={4}
      />
      <button type="submit" disabled={status === "loading"}>
        {status === "loading" ? "Sending..." : "Send"}
      </button>
      {status === "success" && <p>Message sent!</p>}
      {status === "error"   && <p>Something went wrong.</p>}
    </form>
  );
}