Master real-time filtering in React by synchronizing your search state with your data. Learn to derive UI state efficiently without redundant variables.
Previously in this course, we covered Managing State with useState: A Beginner’s Guide to React Hooks to track individual variables and Building an Interactive Search Bar to capture user input. Now, we will connect those pieces to implement filtering, allowing your users to find specific movies in real-time as they type.
In React, a common trap is trying to keep "everything" in state. You might be tempted to create a filteredMovies state variable and update it whenever the user types.
Don't do this.
Instead, we use derived state. Since we already have the full list of movies (from props or initial state) and the current search query (from our controlled input), we can calculate the filtered list during the render. This ensures your UI is always perfectly in sync with the underlying data.
Let's look at how to implement this in our movie-browser project. We will take our master list of movies and apply a .filter() method before mapping over them to display the cards.
JSXimport { useState } from CE9178">'react'; import MovieCard from CE9178">'./MovieCard'; const MovieList = ({ movies }) => { const [searchQuery, setSearchQuery] = useState(""); // Derived state: calculate this on every render const filteredMovies = movies.filter((movie) => movie.title.toLowerCase().includes(searchQuery.toLowerCase()) ); return ( <div> <input type="text" placeholder="Search movies..." value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} /> <div className="movie-grid"> {filteredMovies.map((movie) => ( <MovieCard key={movie.id} movie={movie} /> ))} </div> </div> ); };
In this snippet, filteredMovies is not a state variable. It is a plain JavaScript variable calculated based on the current searchQuery. When the user types, setSearchQuery triggers a re-render, React runs this logic again, and the list updates instantly.
movies array passed down as props (following our earlier work on Rendering Lists of Data).filter logic as shown above.filteredMovies.length is zero, using the concepts from Conditional Rendering.const [filtered, setFiltered] = useState(movies). This leads to "state synchronization hell," where you have to manually update filtered every time movies changes or searchQuery changes. Always calculate it on the fly..toLowerCase() on both the search query and the movie title to ensure your search is case-insensitive.Real-time search is fundamentally a task of state synchronization. By keeping the search input as the "source of truth" and deriving the display list from it, you minimize bugs and make your code significantly easier to reason about. Remember: if a value can be computed from existing state, do not store it in a separate useState hook.
Up next: We'll move beyond simple input handling to Handling Form Submissions to manage more complex user interactions.
Master the art of UI state management by adding a filter toggle to your movie app. Learn to control list rendering using boolean state and checkbox inputs.
Filtering the Movie List
Polishing the UI
Finalizing the Movie Browser
Review of Component Lifecycle
Review of State Management
Building a Modal Component
Introduction to PropTypes
Performance Optimization Basics
Handling Browser History
Working with LocalStorage
Building a Favorites List
Handling Media in React
Introduction to Testing
Debugging React Apps
Deployment Basics
Using External Libraries
Advanced