Forms in React: Mastering Controlled Components

Learn the fundamental React pattern for creating interactive and predictable forms that are easy to manage and validate.

📝

Welcome! Let's learn how to capture user input with forms in React.

/* Let's build a form... */

State: The Single Source of Truth

The foundation of forms in React is state. For each input field, you'll have a piece of state that holds its current value. This makes your React component the "single source of truth" for the form's data. We typically start by initializing the state with <useState>.

Handling User Input with `onChange`

To update the state as the user types, you need an event handler. This function is attached to the input's <onChange> event. Inside the handler, you'll call your state setter function (e.g., setUsername ) with the new value from <event.target.value>.

Controlled Components: Connecting State and UI

A controlled component is an input element whose value is controlled by React. You achieve this by binding the input's <value> prop to your state variable and its <onChange>` prop to your event handler. This creates a two-way data flow: state updates the input, and user actions update the state.

Submitting the Form with `onSubmit`

Finally, to handle the form submission, you attach an <onSubmit> event handler to the <form> element. Inside this function, you must call `event.preventDefault()` to stop the browser's default behavior of reloading the page. Here, you can access the final form data from your state for validation or API calls.

Practice Zone


Interactive Test 1: Match the Concept

Match the form attribute to its correct role in a controlled component.

Arrastra en el orden correspondiente.


Arrastra las opciones:

`onChange={handleChange}`
`<form onSubmit={...}>`
`value={username}`

Completa el código:

Displays state______
Updates state______
Handles submission______
Unlock with Premium

Interactive Test 2: Complete the Code

Rellena los huecos en cada casilla.

function Login() {
  const [username, ] = useState('');

  const handleChange = (e) => {
    setUsername(e.);
  }

  return <input value={username} onChange={handleChange} />;
}
Unlock with Premium

Practice Example: Code Editor

Create a component with an email input and a password input. Both should be controlled components.

Enunciado:

* Escribe el código a continuación. Los caracteres correctos se mostrarán en verde y los incorrectos en rojo.

function SignUpForm() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); return ( <form> <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="Email" /> <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Password" /> </form> ); }

Unlock with Premium

Knowledge Check

In a controlled component, where does the data for the input's value come from?


Unlock with Premium

Forms in Action

Handling forms is more than just text inputs. Let's explore how controlled components adapt to other common form elements and validation strategies.


1. Handling Multiple Inputs

Instead of a separate useState for each input, you can use a single state object. To update it, use the input's name attribute to dynamically choose which property to update. This keeps your code clean and scalable.

const [formData, setFormData] = useState({ email: '', password: '' });

const handleChange = (e) => {
  const { name, value } = e.target;
  setFormData(prevData => ({
    ...prevData,
    [name]: value
  }));
}

2. Other Input Types (textarea, select)

The controlled component pattern works beautifully for other elements too. A textarea uses value and onChange just like a text input. For a select dropdown, you set the value on the <select> tag itself to control the selected option.

<textarea value={bio} onChange={(e) => setBio(e.target.value)} />

<select value={userRole} onChange={(e) => setUserRole(e.target.value)}>
  <option value="user">User</option>
  <option value="admin">Admin</option>
</select>

3. Basic Form Validation

Since you have the form data in your state, you can validate it at any time. A common approach is to check the data inside the `onSubmit` handler before proceeding. You can then set an error message in state to provide feedback to the user.

const handleSubmit = (e) => {
  e.preventDefault();
  if (password.length < 8) {
    setError('Password must be at least 8 characters long.');
  } else {
    setError('');
    // Submit data...
  }
}

Practical Takeaway: The controlled components pattern provides a predictable and powerful way to manage all user input, giving you full control over form data and enabling easy implementation of features like validation and dynamic fields.

React Forms Glossary

Controlled Component
A form input element whose value is controlled by React state. The state is the "single source of truth," and it's updated via an `onChange` handler.
Uncontrolled Component
A form input where the state is handled by the DOM itself. In React, you would typically use a `ref` to get its value when needed, but this is less common.
`event.target`
A property of the event object that refers to the DOM element that triggered the event. For forms, `event.target.value` gives you the current value of the input.
`event.preventDefault()`
A method called within an event handler (typically `onSubmit`) to stop the browser's default action. For forms, this prevents a full-page reload on submission.
Single Source of Truth
A core principle in React where the state of your component is the definitive source of data for the UI. Any changes to the data must happen by updating the state.