Submitting a form
To group fields and submit them, use a <form> with the onSubmit event. The
first thing inside the handler is e.preventDefault(), so the browser doesn't
reload the page (its default behavior):
function Login() {
const [username, setUsername] = useState("");
function submit(e) {
e.preventDefault();
console.log("Submitting:", username);
}
return (
<form onSubmit={submit}>
<input value={username} onChange={(e) => setUsername(e.target.value)} />
<button type="submit">Sign in</button>
</form>
);
}
onSubmit fires when you click a <button type="submit"> (or press Enter
inside the input).
Multiple fields
With multiple fields, the usual approach is one state per field, each controlled:
function SignUp() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
function submit(e) {
e.preventDefault();
console.log({ name, email });
}
return (
<form onSubmit={submit}>
<input value={name} onChange={(e) => setName(e.target.value)} />
<input value={email} onChange={(e) => setEmail(e.target.value)} />
<button type="submit">Register</button>
</form>
);
}
Uncontrolled inputs (a bird's-eye view)
There's an alternative: let the DOM manage the value and read it only when
needed via a ref (useRef). These are uncontrolled inputs:
function Search() {
const inputRef = useRef(null);
function submit(e) {
e.preventDefault();
console.log(inputRef.current.value); // read on submit
}
return (
<form onSubmit={submit}>
<input ref={inputRef} />
<button>Search</button>
</form>
);
}
They're handy for simple cases, but you lose live validation and full control. In most cases controlled inputs are preferred.