Forms & Controlled Inputs

In plain HTML, an input manages its own value internally — the browser just remembers what you typed. In React, the standard pattern is a controlled input: the input's value comes from state, and every keystroke updates that state, so React is always the single source of truth for what the field contains.

A single controlled input

JSX NameForm.jsx
import { useState } from "react";

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

  return (
    <>
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <p>Hello, {name || "stranger"}!</p>
    </>
  );
}
Rendered output
Typing "Priya" into the input updates the paragraph
live, character by character:
Hello, stranger!  →  Hello, P!  → … →  Hello, Priya!

value={"{name}"} makes React set the input's displayed text from state, and onChange fires on every keystroke, updating that same state with whatever was just typed. Together, the input's on-screen value and the name variable never fall out of sync.

Handling form submission

JSX SearchForm.jsx
function SearchForm() {
  const [query, setQuery] = useState("");

  function handleSubmit(e) {
    e.preventDefault();
    console.log("Searching for:", query);
  }

  return (
    <form onSubmit={handleSubmit}>
      <input value={query} onChange={(e) => setQuery(e.target.value)} />
      <button type="submit">Search</button>
    </form>
  );
}
Console, after typing "react" and clicking Search
Searching for: react

e.preventDefault() stops the browser's default behavior of reloading the page on form submission, which is almost always what you want in a React app — the page stays put, and your own code handles what happens next.

Note: if you set an input's value from state but forget the onChange handler, the field becomes read-only — React renders the value you gave it and then blocks every keystroke from changing it, since nothing is telling state to update. An input with a value but no change handler is one of the most common "why won't this typing work" bugs in early React code.