Hello! Welcome to your next lesson.
In our last two sessions, we built a solid understanding of the useState hook. We learned how to add state to our components and, crucially, how to update that state reliably using the functional updater pattern, especially when the new state depends on the old.
Today, we'll apply that knowledge to one of the most fundamental tasks in web development: handling user input. Our goal is to build controlled form inputs for text, select, and checkboxes using useState. This is a core skill you'll use constantly, whether building a login page, a search bar, or an e-commerce checkout.
What Are Controlled Components?
In React, the term "controlled component" refers to a form input whose value is controlled by React state. Instead of the HTML input element managing its own internal state (like what happens by default), we let our component's state be the "single source of truth."
This creates a two-way data binding loop:
- State to UI: The React state dictates what the input field displays.
- UI to State: User actions (like typing) trigger an event handler that updates the React state.
This gives us complete control over the form data at all times.

Let's see how to implement this pattern.
1. The Core Pattern: Controlled Text Inputs
The most common form element is the text input. Creating a controlled text input requires two key pieces:
- A
useStatevariable to hold the input's value. - Binding the input's
valueattribute to this state variable. - Using the
onChangeevent handler to update the state with the user's input, which we get fromevent.target.value.
The following video provides a clear, step-by-step demonstration.
Full React Tutorial #27 - Controlled Inputs (forms)
Watch this segment from the "Full React Tutorial" by Net Ninja. It perfectly demonstrates how to set up a state variable and connect it to a text input to make it a controlled component.
Watch from 04:08 to 06:57. Pay close attention to how the value attribute and the onChange handler work together. The instructor also helpfully logs the state to the screen so you can see it update in real-time.
To summarize the pattern for a text input:
import { useState } from 'react';
function MyForm() {
// 1. Declare a state variable to hold the input value
const [name, setName] = useState('');
return (
<input
type="text"
// 2. Bind the input's value to the state variable
value={name}
// 3. Update the state when the user types
onChange={(e) => setName(e.target.value)}
/>
);
}
This same pattern applies directly to <textarea> elements as well, as they also use the value and onChange attributes in the same way.
For a deeper conceptual reading on this topic, the article "Data binding in React" by Josh W. Comeau is an excellent resource. You can refer to the introductory section to reinforce your understanding of controlled fields.
2. Handling Selects and Checkboxes
While other inputs follow a similar principle, there are slight but important differences in their implementation.
Select (Dropdown) Menus
A <select> element is handled almost identically to a text input. You bind the value prop on the <select> tag itself to your state variable, and the onChange handler will give you the chosen <option>'s value.
Full React Tutorial #27 - Controlled Inputs (forms)
Let's return to the Net Ninja video. The next section demonstrates how to control a <select> element.
Watch from 07:48 to 09:20. Notice that the value and onChange logic on the <select> tag is exactly the same as it was for the text input.
The pattern for a select input:
const [selection, setSelection] = useState('option1');
<select value={selection} onChange={(e) => setSelection(e.target.value)}>
<option value="option1">Option 1</option>
<option value="option2">Option 2</option>
</select>
Checkbox Inputs
Checkboxes are a bit different. Instead of a text value, their state is binary: checked or unchecked (a boolean).
- Instead of the
valueattribute, we use thecheckedattribute to control its state. - In the
onChangehandler, we get the new state fromevent.target.checked, which will betrueorfalse.
This video explains it clearly.
ReactJS : Working with Forms with useState Hook (radio buttons,checkboxes,dropdown menus) Part2
This video from NoobCoder focuses on different form inputs and provides a great explanation for checkboxes.
Watch from 03:04 to 05:30. Focus on how the checked attribute is used instead of value, and how the handler function uses e.target.checked to update the boolean state.
The pattern for a checkbox:
const [isChecked, setIsChecked] = useState(false);
<label>
<input
type="checkbox"
// Use the `checked` attribute for checkboxes
checked={isChecked}
// Update state using the boolean from `e.target.checked`
onChange={(e) => setIsChecked(e.target.checked)}
/>
Accept terms and conditions
</label>
The Big Picture
The simple patterns you learned today are the building blocks for any form in React, no matter how complex. By combining them, you can build rich, interactive forms.

In a form with many fields like the one above, you'll often manage all the values in a single state object rather than many separate useState calls. We'll cover that more efficient pattern in an upcoming lesson on building a multi-field contact form.
Conclusion
You've now learned how to connect form inputs to React's state management system, giving you full control over user data. This is a crucial step toward building the interactive applications you're aiming for, like your e-commerce project.
Key Takeaways:
- Controlled Components: Form inputs whose values are controlled by React state. The state is the single source of truth.
- Text and Select Inputs: Use the
valueattribute to display the state ande.target.valuein theonChangehandler to update it. - Checkbox Inputs: Use the
checkedattribute to display the state ande.target.checkedin theonChangehandler to update it. - The Two-Way Loop: The
value/checkedprop sends state to the input, and theonChangeprop sends user actions back to update the state.
Preview of Next Lesson:
Now that we can control the data within our form inputs, the next logical step is to do something with that data. In the next lesson, we will learn how to handle form submission, including preventing the default browser behavior.