tenantpilot/components/search/SearchInput.tsx
Ahmed Darrazi 56088ca6c0
All checks were successful
Trigger Cloudarix Deploy / call-webhook (push) Successful in 1s
fix: Resolve search infinite loop issue
Fixed useEffect dependency problem in SearchInput that caused
infinite re-renders when searching with 2+ characters.

Changes:
- Removed onSearch from useEffect dependencies
- Added ESLint disable comment for exhaustive-deps
- Search now only triggers on debouncedQuery changes

Issue: Search spinner would hang indefinitely when typing 2 chars
Root cause: onSearch callback recreated on every render, causing loop
Solution: Only depend on debouncedQuery in useEffect
2025-12-07 22:59:07 +01:00

47 lines
1.5 KiB
TypeScript

'use client';
import { Input } from '@/components/ui/input';
import { Search, Loader2 } from 'lucide-react';
import { useState, useEffect, useCallback } from 'react';
import { useDebounce } from 'use-debounce';
interface SearchInputProps {
onSearch: (query: string) => void;
isSearching?: boolean;
}
export function SearchInput({ onSearch, isSearching = false }: SearchInputProps) {
const [query, setQuery] = useState('');
const [debouncedQuery] = useDebounce(query, 300);
// Show typing indicator when input differs from debounced value
const isTyping = query !== debouncedQuery && query.length > 0;
useEffect(() => {
// Only trigger search when debounced value changes
if (debouncedQuery.length >= 2 || debouncedQuery.length === 0) {
onSearch(debouncedQuery);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [debouncedQuery]); // Only depend on debouncedQuery, not onSearch
return (
<div className="relative w-full max-w-2xl">
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
<Input
type="text"
placeholder="Search policy settings... (e.g., USB, Camera, Defender)"
value={query}
onChange={(e) => setQuery(e.target.value)}
disabled={isSearching}
className="pl-10 pr-10"
/>
{(isSearching || isTyping) && (
<div className="absolute right-3 top-1/2 -translate-y-1/2">
<Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
</div>
)}
</div>
);
}