← Back to React Course | Chapter 7: Forms & User Input | Lesson 1 of 8

Working with Forms in React

A form in React is like a paper form you fill out, except React watches every letter you type and remembers it instantly.

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

markup
<!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

markup
<!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

markup
<!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>
Common Mistakes
  1. Forgetting an onChange handler on an input, which makes it impossible to type anything into it.
  2. Not calling event.preventDefault() in the submit handler, causing the page to reload.
  3. Reading form values from the DOM directly instead of from React state.
Chapter Summary
  • 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.
Browser Support

No React-version restriction — forms use standard HTML elements supported in all browsers.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.