Every React Developer Has Done This at Least Once 😅
const filteredProducts = products.filter((product) =>
product.title.toLowerCase().includes(search.toLowerCase())
);
It works...
Until your API returns 10,000+ products.
Now you're downloading thousands of unnecessary records just to search for a single keyword.
- ❌ Slower loading
- ❌ Wasted bandwidth
- ❌ High memory usage
- ❌ Doesn't scale
So what's the better approach?
🚀 The Solution: Server-Side Search
Instead of downloading every product and filtering them inside React, let your backend search the database and return only the matching records.
When you combine this with TanStack React Query, you also get:
- ✅ Automatic caching
- ✅ Loading states
- ✅ Background refetching
- ✅ Request deduplication
- ✅ Cleaner server-state management
In this guide, we'll build a production-ready server-side search using React Query.
Why Server-Side Search?
Imagine an ecommerce application with 100,000 products.
❌ Client-Side Search
Frontend
↓
GET /products
↓
100,000 products
↓
React filters data
Problems
- Huge API responses
- Slow initial loading
- High memory usage
- Wasted network bandwidth
- Poor scalability
✅ Server-Side Search
Frontend
↓
GET /products?search=iphone
↓
Backend searches database
↓
Returns only matching products
Benefits
- Faster responses
- Smaller payloads
- Better scalability
- Lower memory usage
- Better user experience
Project Structure
src
├── api
│ productApi.js
│
├── hooks
│ useProducts.js
│
├── pages
│ ProductPage.jsx
│
└── components
SearchInput.jsx
Keeping your API logic separate from your UI makes applications much easier to maintain as they grow.
Step 1 — Install React Query
npm install @tanstack/react-query axios
Create your Query Client.
const queryClient = new QueryClient();
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>;
Step 2 — Create the API Function
Your backend should support query parameters like this:
GET /products?search=iphone
Create the API function.
export const getProducts = async (search) => {
const response = await axios.get("/products", {
params: {
search,
},
});
return response.data;
};
Instead of filtering on the frontend, we're sending the search value directly to the backend.
Step 3 — Create a React Query Hook
export const useProducts = (search) => {
return useQuery({
queryKey: ["products", search],
queryFn: () => getProducts(search),
});
};
This is where React Query really shines.
Every unique search term gets its own cache automatically.
Searching for:
iphone
and later:
samsung
creates two independent cached queries without any extra code.
Step 4 — Create Search State
const [search, setSearch] = useState("");
<input
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="Search products..."
/>
Step 5 — Fetch Products
const { data, isLoading } = useProducts(search);
Every time the search changes:
User Types
↓
React State Updates
↓
React Query
↓
Backend API
↓
Updated Products
No client-side filtering required.
Step 6 — Render Products
{
data?.products?.map((product) => (
<ProductCard key={product.id} product={product} />
));
}
That's it.
React Query automatically handles:
- Caching
- Loading states
- Background refetching
- Request deduplication
- Server-state synchronization
⚡ Bonus Improvement: Debounce Search
Without debouncing:
i
ip
iph
ipho
iphon
iphone
That's 6 API requests.
Instead, debounce the search input by 300–500ms so the request is only sent after the user pauses typing.
This significantly reduces unnecessary API calls while keeping the UI responsive.
Complete Flow
User Types
↓
Search State Updates
↓
React Query detects new queryKey
↓
Calls Backend API
↓
Database searches records
↓
Returns matching products
↓
React UI updates
Simple.
Clean.
Scalable.
Why React Query Makes This Better
Without React Query, you'd have to manually manage:
- Loading states
- Error handling
- Caching
- Duplicate requests
- Background refetching
React Query gives you all of these features out of the box, making it a perfect companion for server-side search.
Final Thoughts
Client-side searching is completely fine for small datasets.
However, once you're building applications like:
- 🛒 Ecommerce
- 📊 Admin Dashboards
- 👥 CRM Systems
- 📦 Inventory Management
- 🏢 HR Platforms
server-side search becomes the professional solution.
Your frontend stays lightweight, your backend does the heavy lifting, and your users enjoy a much faster experience.
🎥 Watch the Full Video Tutorial
This article is part of my Modern Ecommerce in React & Modern Stacks (2026) series.
▶️ Full Playlist
https://www.youtube.com/watch?v=Jluy-W9eP-4&list=PL_02r0p8Ku_6tR8L-n-yj7MW8rrMtswwk&index=1
In Episode 11, I walk through the complete implementation of server-side search using React Query, Axios, and backend query parameters.
👉 Watch Episode 11
https://www.youtube.com/watch?v=QrA5_bvORZU&list=PL_02r0p8Ku_6tR8L-n-yj7MW8rrMtswwk&index=11
If you're following the full series, you'll learn how to build a production-ready ecommerce application from scratch using modern React technologies.
⭐ If this article helped you, consider following Codeek for more tutorials on React, TypeScript, Chakra UI, TanStack Query, Zustand, Stripe, Firebase, and full-stack development.
Happy coding! 🚀

Top comments (0)