From 337888fe479f1e6b8abae64876415b28255356f9 Mon Sep 17 00:00:00 2001 From: sebastjanartic <45803536-sebastjanartic@users.noreply.replit.com> Date: Thu, 28 Aug 2025 11:53:56 +0000 Subject: [PATCH] Improve search performance by debouncing requests and filtering short queries Adds a debounce function to the client-side search header to limit API calls and filters out search queries shorter than 2 characters on the server-side to improve performance. Replit-Commit-Author: Agent Replit-Commit-Session-Id: d7424866-83d1-4486-a212-ac12b4c7becf Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8cc42625-c1f5-4e43-99bd-77f2c4dedee2/d7424866-83d1-4486-a212-ac12b4c7becf/66oOTXh --- client/src/components/search-header.tsx | 21 +++++++++++++++++++-- server/routes.ts | 9 ++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/client/src/components/search-header.tsx b/client/src/components/search-header.tsx index ec8e040..8088e5e 100644 --- a/client/src/components/search-header.tsx +++ b/client/src/components/search-header.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useState, useCallback } from "react"; import { Search, Play, Menu, Grid3X3, List } from "lucide-react"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; @@ -17,9 +17,26 @@ export default function SearchHeader({ }: SearchHeaderProps) { const [searchQuery, setSearchQuery] = useState(""); + // Debounce function to delay search API calls + const debounce = useCallback((func: Function, delay: number) => { + let timeoutId: NodeJS.Timeout; + return (...args: any[]) => { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => func(...args), delay); + }; + }, []); + + // Debounced search function - waits 500ms after user stops typing + const debouncedSearch = useCallback( + debounce((query: string) => { + onSearch(query); + }, 500), + [onSearch, debounce] + ); + const handleSearchChange = (value: string) => { setSearchQuery(value); - onSearch(value); + debouncedSearch(value); }; return ( diff --git a/server/routes.ts b/server/routes.ts index 514a0d1..b48ee34 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -176,10 +176,13 @@ export async function registerRoutes(app: Express): Promise { const offset = parseInt(req.query.offset as string) || 0; const search = req.query.search as string; - console.log(`Fetching videos: limit=${limit}, offset=${offset}, search=${search}`); + // Skip search for queries shorter than 2 characters for performance + const searchQuery = search && search.length >= 2 ? search : undefined; + + console.log(`Fetching videos: limit=${limit}, offset=${offset}, search=${searchQuery}`); - const videos = await storage.getVideos(limit, offset, search); - const total = await storage.getVideoCount(search); + const videos = await storage.getVideos(limit, offset, searchQuery); + const total = await storage.getVideoCount(searchQuery); console.log(`Returning ${videos.length} videos`);