R
Rishtaara
React: The Complete Guide
Lesson 10 of 28Article20 min

Forms — Submit, Textarea, Select, Checkbox & Radio

In a controlled component, React state is the single source of truth for input values. Every keystroke updates state, which re-renders the input.

React Forms — controlled components

In a controlled component, React state is the single source of truth for input values. Every keystroke updates state, which re-renders the input.

Real-life example: Controlled inputs are like a teacher checking your homework live — every word you write is copied to their notebook (state) instantly.

Controlled text input
import { useState } from "react";

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

  return (
    <form>
      <label>
        Name:
        <input value={name} onChange={(e) => setName(e.target.value)} />
      </label>
      <p>Hello, {name || "guest"}!</p>
    </form>
  );
}

Submit — handle form send

Use onSubmit on the form and e.preventDefault() to handle data in JavaScript without reloading the page.

Real-life example: Submit is pressing Send on WhatsApp — preventDefault keeps you in the chat app instead of opening a new blank browser tab.

Form submit handler
function SignupForm() {
  const [email, setEmail] = useState("");

  function handleSubmit(e) {
    e.preventDefault();
    if (!email.includes("@")) {
      alert("Enter a valid email");
      return;
    }
    console.log("Signed up:", email);
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
      />
      <button type="submit">Sign up</button>
    </form>
  );
}

Textarea

Textarea works like input — bind value and onChange to state for multi-line text.

Real-life example: Textarea is a big notebook page; input is a single-line sticky note.

Controlled textarea
const [bio, setBio] = useState("");

<textarea
  value={bio}
  onChange={(e) => setBio(e.target.value)}
  rows={4}
  placeholder="Tell us about yourself"
/>

Select — dropdown

Select uses value and onChange like input. Option values are strings unless you convert them.

Real-life example: Select is a restaurant menu — you pick one dish (option) from the list.

Controlled select
const [course, setCourse] = useState("react");

<select value={course} onChange={(e) => setCourse(e.target.value)}>
  <option value="react">React</option>
  <option value="js">JavaScript</option>
  <option value="css">CSS</option>
</select>

Multiple Inputs — one handler

Store form fields in one state object. Use name attributes and e.target.name to update the right field.

Real-life example: One handler for many inputs is like one receptionist updating different forms — they read the form name tag (name attribute) to know which file to update.

Object state for many fields
const [form, setForm] = useState({ name: "", email: "", course: "react" });

function handleChange(e) {
  const { name, value } = e.target;
  setForm((prev) => ({ ...prev, [name]: value }));
}

<input name="name" value={form.name} onChange={handleChange} />
<input name="email" value={form.email} onChange={handleChange} />

Checkbox

Checkbox uses checked instead of value. Toggle boolean state on change.

Real-life example: Checkbox is agreeing to terms — checked means yes, unchecked means no.

Controlled checkbox
const [agreed, setAgreed] = useState(false);

<label>
  <input
    type="checkbox"
    checked={agreed}
    onChange={(e) => setAgreed(e.target.checked)}
  />
  I agree to the Rishtaara terms
</label>

Radio buttons

Radio buttons share one name and one piece of state — only one option selected at a time.

Real-life example: Radio buttons are like choosing one ice cream flavor — pick vanilla OR chocolate, not both in the same group.

Radio group
const [plan, setPlan] = useState("free");

<label>
  <input
    type="radio"
    name="plan"
    value="free"
    checked={plan === "free"}
    onChange={(e) => setPlan(e.target.value)}
  />
  Free
</label>
<label>
  <input
    type="radio"
    name="plan"
    value="pro"
    checked={plan === "pro"}
    onChange={(e) => setPlan(e.target.value)}
  />
  Pro
</label>