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
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>
</>
);
}
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
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>
);
}
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.
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.