Working with Forms in React
In this page:
Why Forms Need Special Handling in React
In plain HTML, a browser manages form input values on its own. In React, you usually want the input's value to live in state instead, so the component can read, validate, or react to it as the user types. This is what makes a form React-controlled.
Note: Start simple: one useState per field is fine for small forms.
Warning: Don't mix uncontrolled inputs (no value prop) with controlled ones in the same form — pick one style per input.
Example: Why Forms Need Special Handling in React
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function App() {
const [name, setName] = React.useState("");
return <input value={name} onChange={e => setName(e.target.value)} placeholder="Your name" />;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>
Handling Form Submission
The <form> element's onSubmit event fires when the user presses Enter or clicks a submit button. Calling event.preventDefault() inside it stops the browser's default behavior of reloading the page, letting your JavaScript handle the submitted data instead.
Note: Always destructure or read the event's target inside the handler, not from an external ref, to keep the handler pure.
Warning: Forgetting preventDefault() causes the whole page to reload, wiping out any React state you had.
Example: Handling Form Submission
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function App() {
const [name, setName] = React.useState("");
const handleSubmit = e => { e.preventDefault(); alert("Submitted: " + name); };
return (
<form onSubmit={handleSubmit}>
<input value={name} onChange={e => setName(e.target.value)} />
<button type="submit">Submit</button>
</form>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>
Managing Multiple Fields at Once
For forms with several fields, storing all of them in one state object (instead of one useState per field) keeps things organized. A single handleChange function can update the right field using the input's name attribute.
Note: Use the input's name attribute to look up which field to update, so one handler works for every field.
Warning: When spreading previous state ({...form, [name]: value}), forgetting the spread wipes out every other field's value.
Example: Managing Multiple Fields at Once
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function App() {
const [form, setForm] = React.useState({ first: "", last: "" });
const handleChange = e => setForm({ ...form, [e.target.name]: e.target.value });
return (
<div>
<input name="first" value={form.first} onChange={handleChange} placeholder="First" />
<input name="last" value={form.last} onChange={handleChange} placeholder="Last" />
<p>Full name: {form.first} {form.last}</p>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>
- Forgetting an onChange handler on an input, which makes it impossible to type anything into it.
- Not calling event.preventDefault() in the submit handler, causing the page to reload.
- Reading form values from the DOM directly instead of from React state.
- Forms in React are built from regular HTML input elements enhanced with React state.
- The onSubmit handler on the <form> tag is where you process the final values.
- preventDefault() stops the browser's default full-page-reload submit behavior.
- React re-renders the input's displayed value from state on every keystroke.
No React-version restriction — forms use standard HTML elements supported in all browsers.
Chapter Quiz — Complete all 8 topics to unlock
0/8 topics done
Complete these topics first: