Global search bars are common, but debouncing search queries without messy prop drilling can get tricky. Let's create a clean, performant global search context with built-in debounce — no third-party libraries needed.
Why Use a Debounced Global Search?
Benefits include:
- Reducing API call spam
- Consistent search state across unrelated components
- Improved UX with minimal extra code
Step 1: Create the Search Context
This context will handle search term updates and debounce internally:
// searchContext.js import { createContext, useContext, useState, useRef } from "react"; const SearchContext = createContext(null); export function SearchProvider({ children }) { const [searchTerm, setSearchTerm] = useState(""); const debounceRef = useRef(null); const updateSearch = (term) => { if (debounceRef.current) clearTimeout(debounceRef.current); debounceRef.current = setTimeout(() => { setSearchTerm(term); }, 300); // 300ms debounce }; return ( <SearchContext.Provider value={{ searchTerm, updateSearch }}> {children} </SearchContext.Provider> ); } export function useSearch() { return useContext(SearchContext); }
Step 2: Create a Search Input Component
This component will update the global search context on typing:
// SearchInput.js import { useSearch } from "./searchContext"; function SearchInput() { const { updateSearch } = useSearch(); const handleChange = (e) => { updateSearch(e.target.value); }; return <input type="text" placeholder="Search..." onChange={handleChange} />; } export default SearchInput;
Step 3: Use Search Results Anywhere
Any component can now subscribe to the debounced search term:
// SearchResults.js import { useSearch } from "./searchContext"; function SearchResults() { const { searchTerm } = useSearch(); return <div> <p>Searching for: <strong>{searchTerm}</strong></p> {/* Add your search fetching logic here */} </div>; } export default SearchResults;
Step 4: Wrap Your App with the Provider
// App.js import { SearchProvider } from "./searchContext"; import SearchInput from "./SearchInput"; import SearchResults from "./SearchResults"; function App() { return ( <SearchProvider> <SearchInput /> <SearchResults /> </SearchProvider> ); } export default App;
Pros and Cons
✅ Pros
- Built-in debounce without extra packages
- Global search term accessible anywhere
- Simple and lightweight
⚠️ Cons
- Fixed debounce delay (hardcoded 300ms)
- Doesn't cancel already-fired API calls
- Minimal error handling for complex search behaviors
🚀 Alternatives
- use-debounce library for more control
- React Query for API-layer search state management
Summary
By wrapping a simple debounce inside a context provider, you can create elegant, scalable search systems in React with almost no overhead. Perfect for dashboards, admin panels, and internal tools where performance matters.
For a much more extensive guide on getting the most out of React portals, check out my full 24-page PDF file on Gumroad. It's available for just $10:
Using React Portals Like a Pro.
If you found this helpful, you can support me here: buymeacoffee.com/hexshift
Top comments (0)