Building an Interactive Search Bar: Controlled Inputs in React
Learn to build an interactive search bar in React. Master controlled inputs by synchronizing form values with local state for a reactive, responsive UI.
Previously in this course, we explored introduction to react state: making your ui interactive and mastered managing state with usestate: a beginner's guide to react hooks. In this lesson, we apply those fundamentals to build a functional search bar, moving from static HTML to dynamic, data-driven inputs.
The Concept: Controlled Inputs
In standard HTML, an <input> field maintains its own internal state. When a user types, the browser automatically updates the display. However, in React, we prefer the "Single Source of Truth" pattern.
We achieve this using controlled inputs. A controlled input is a form element whose value is driven by React state rather than the browser's internal DOM state. When the user types, we capture the event, update our state, and React re-renders the component to display the new value.
This approach gives us full control over the data, allowing us to validate, transform, or log input in real-time.
Building the Search Bar
To build our search bar, we need two things: an input element and a piece of state to track what the user is typing. We’ll use the onChange event listener to trigger a state update every time a key is pressed.
Here is how you implement it in your SearchBar component:
JSXimport { useState } from CE9178">'react'; function SearchBar() { const [searchTerm, setSearchTerm] = useState(CE9178">''); const handleChange = (event) => { const newValue = event.target.value; setSearchTerm(newValue); // Logging state changes to the console console.log("Current search term:", newValue); }; return ( <div className="search-container"> <input type="text" placeholder="Search for movies..." value={searchTerm} onChange={handleChange} /> <p>Searching for: {searchTerm}</p> </div> ); } export default SearchBar;
Breaking down the code:
useState(''): We initialize our state with an empty string. This represents the starting value of the search bar.value={searchTerm}: This is the "controlled" part. We tell the input that its value must always match thesearchTermstate variable.onChange={handleChange}: Whenever the user types, the browser fires an event. We accessevent.target.valueto get the current characters in the box and update our state.
Hands-on Exercise
It's time to advance our movie-browser project. Follow these steps:
- Create a new file named
SearchBar.jsxin your components folder. - Implement the code above, ensuring you import
useStatefrom React. - Add this component to your main
App.jsxfile to see it in action. - Open your browser's Developer Tools (F12) and go to the "Console" tab. Type into the input field and confirm that every keystroke logs the updated state correctly.
Common Pitfalls
Even experienced developers run into these issues when starting with forms:
- Forgetting the
onChangehandler: If you provide avalueprop to an input but don't provide anonChangehandler, the input will become read-only. You won't be able to type anything! - Assuming State is Synchronous: Remember that calling
setSearchTermdoes not update the variable immediately in the current execution context. If youconsole.log(searchTerm)immediately after setting it, you will see the old value. Always use the event object (event.target.value) if you need the immediate new value. - Over-complicating state: For a simple search bar, you don't need complex patterns. Keep it simple with
useStateuntil you reach the requirements of react form handling: controlled vs. uncontrolled components.
Recap
By controlling our input, we've bridged the gap between user interaction and application state. We've learned that:
- Controlled inputs allow React to own the data within a form field.
- The
valueprop links the input to ouruseStatevariable. - The
onChangeevent is the primary mechanism for capturing user input.
You now have a responsive search bar that tracks user intent. This component is the foundation for the filtering logic we will build in upcoming lessons.
Up next: We will explore Handling Click Events to make our application even more interactive.
Work with me

Next.js Full-Stack Web App Development
A fast, SEO-ready full-stack web app built with Next.js 16 — from idea to deployed product, by an engineer who ships to production.

Headless WordPress + Next.js Frontend Development
Keep WordPress for content, get a lightning-fast Next.js frontend. The best of both worlds — familiar editing, modern speed.