Form data is the information entered or held while a user interacts with fields such as text inputs, checkboxes, drop-downs, and file uploads. In React, forms commonly keep current values in component state so the application controls both the data and its flow. section 5.1.3 section 9.0
Manage form data through two main approaches:
- Use controlled inputs: store current values in React state, pass those values to fields, and update state from change events. This keeps application logic in React and lets it enforce rules. section 9.0
- Use uncontrolled inputs: let HTML and the browser own the form state, then read values from React when needed. This uses built-in handling but gives the application less control. section 9.0
- For many similar fields, store all values in one object and use each input's name as the key to update. A functional state update preserves the other fields. section 9.2.3
A reusable address-form pattern
Initialize one state object with address1, address2, zip, city, state, and country as empty strings. Attach one onChange handler to every input; read evt.target.name and evt.target.value, then update with { ...oldData, [key]: value }. Each input receives its value from the matching state property. section 9.2.3
Listing 9.5 Simpler address form
import { useState } from "react";
function Address() {
const [data, setData] = useState({
address1: "",
address2: "",
zip: "",
city: "",
state: "",
country: "",
});
const onChange = (evt) => {
const key = evt.target.name; #1
const value = evt.target.value; #2
setData((oldData) =>
({ ...oldData, [key]: value })); #3
};
return (
<form style={{ display: "flex", flexDirection: "column" }}>
<label>
Address line 1:
<input
value={data.address1}
name="address1" #4
onChange={onChange} #4
/>
</label>
<label>
Address line 2:
<input
value={data.address2}
name="address2" #4
onChange={onChange} #4
/>
</label>
<label>
Zip:
<input
value={data.zip}
name="zip" #4
onChange={onChange} #4
/>
</label>
<label>
City:
<input
value={data.city}
name="city" #4
onChange={onChange} #4
/>
</label>
<label>
State:
<input
value={data.state}
name="state" #4
onChange={onChange} #4
/>
</label>
<label>
Country:
<input
value={data.country}
name="country" #4
onChange={onChange} #4
/>
</label>
<pre>{JSON.stringify(data, true, 2)}</pre> #5
</form>
);
}
function App() {
return <Address />;
}
export default App;
Inspect the complete simpler address-form listing, including shared state, name-based updates, and controlled input values. section 9.2.3


