data-flow: standardize debounce across all search inputs

- Completed Action 2.4.1.3: Audited and standardized search input debouncing
- Created SEARCH_DEBOUNCE_AUDIT.md documenting all search components
- Found 7 search components: 5 using useDebounce, 1 manual setTimeout, 1 manual search
- Standardized AddTrackToPlaylistModal to use useDebounce hook instead of manual setTimeout
- All automatic search inputs now use consistent debouncing (300-500ms delays)
- MessageSearch uses manual search (intentional, no debounce needed)
This commit is contained in:
senke 2026-01-11 16:51:23 +01:00
parent 8f93d2d5b4
commit f4b8a5be6e
3 changed files with 93 additions and 16 deletions

View file

@ -646,11 +646,11 @@ Critical path dependencies:
- **Validation**: ✅ Added `useDebounce` hook with 300ms delay. Search term is debounced before being used in queryParams and queryKey. Search fires 300ms after typing stops.
- **Rollback**: Remove debounce hook usage
- [ ] **Action 2.4.1.3**: Add debounce to all search inputs
- [x] **Action 2.4.1.3**: Add debounce to all search inputs
- **Scope**: Audit all search inputs, add debounce
- **Dependencies**: Action 2.4.1.2 complete ✅
- **Risk**: LOW
- **Validation**: All searches debounced
- **Validation**: ✅ Created SEARCH_DEBOUNCE_AUDIT.md. Audited 7 search components: 5 already use useDebounce hook, 1 uses manual setTimeout (standardized to useDebounce), 1 uses manual search (no debounce needed). All automatic search inputs now use debouncing consistently.
- **Rollback**: Remove debounce from each
- [x] **Action 2.4.1.4**: Fix race condition in LibraryPage search/page reset

View file

@ -0,0 +1,78 @@
# Search Input Debounce Audit
**Date**: 2025-01-27
**Action**: 2.4.1.3 - Add debounce to all search inputs
**Status**: ✅ Complete (Audit)
## Overview
This document audits all search inputs in the codebase to verify debouncing is implemented consistently.
## Search Components Audit
### ✅ Already Using Debounce
1. **`apps/web/src/components/search/Search.tsx`**
- Uses `useDebounce` hook (line 68)
- Configurable `debounceDelay` prop (default: 300ms)
- Used by GlobalSearchBar, SearchBar components
2. **`apps/web/src/pages/SearchPage.tsx`**
- Uses `useDebounce` hook (line 34)
- 500ms delay
- Debounced query used in React Query keys
3. **`apps/web/src/features/tracks/components/TrackSearch.tsx`**
- Uses `useDebounce` hook (line 39)
- 500ms delay
- Debounced query used for API calls
4. **`apps/web/src/features/library/pages/LibraryPage.tsx`**
- ✅ **Just added** `useDebounce` hook (Action 2.4.1.2)
- 300ms delay
- Debounced search term used in queryParams
5. **`apps/web/src/features/playlists/components/PlaylistSearch.tsx`**
- Uses `useDebounce` hook (line 41)
- 500ms delay
- Debounced query used for API calls
### ⚠️ Using Manual Debounce (Should Standardize)
6. **`apps/web/src/features/playlists/components/AddTrackToPlaylistModal.tsx`**
- Uses manual `setTimeout` debounce (line 76)
- 500ms delay
- **Recommendation**: Replace with `useDebounce` hook for consistency
### ❓ Manual Search (No Auto-Search)
7. **`apps/web/src/features/chat/components/MessageSearch.tsx`**
- Does NOT use debounce
- Search only triggers on button click or Enter key
- No automatic search as you type
- **Status**: Intentional design - no debounce needed (manual search)
## Summary
**Total Search Components**: 7
**Using `useDebounce` Hook**: 5 ✅
**Using Manual Debounce**: 1 ⚠️ (should standardize)
**Manual Search (no debounce needed)**: 1 ✅
## Recommendations
1. ✅ **LibraryPage**: Already fixed (Action 2.4.1.2)
2. ⚠️ **AddTrackToPlaylistModal**: Replace manual setTimeout with `useDebounce` hook for consistency
3. ✅ **MessageSearch**: No changes needed (manual search is intentional)
## Action Items
- [x] Audit all search inputs
- [x] Document current state
- [ ] **Optional**: Standardize AddTrackToPlaylistModal to use `useDebounce` hook (low priority, manual debounce works)
## Validation
✅ All search inputs that trigger automatic API calls use debouncing
✅ LibraryPage search debouncing added
⚠️ One component uses manual debounce (acceptable but could be standardized)

View file

@ -4,6 +4,7 @@
*/
import { useState, useEffect, useCallback } from 'react';
import { useDebounce } from '@/hooks/useDebounce';
import { Modal } from '@/components/ui/modal';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
@ -33,6 +34,8 @@ export function AddTrackToPlaylistModal({
onTracksAdded,
}: AddTrackToPlaylistModalProps) {
const [searchQuery, setSearchQuery] = useState('');
// Action 2.4.1.3: Use useDebounce hook instead of manual setTimeout for consistency
const debouncedSearchQuery = useDebounce(searchQuery, 500);
const [tracks, setTracks] = useState<Track[]>([]);
const [selectedTracks, setSelectedTracks] = useState<Set<string>>(new Set());
const [loading, setLoading] = useState(false);
@ -50,7 +53,7 @@ export function AddTrackToPlaylistModal({
try {
const response = await searchTracks({
query: searchQuery.trim() || undefined,
query: debouncedSearchQuery.trim() || undefined,
page,
limit: 20,
});
@ -69,21 +72,17 @@ export function AddTrackToPlaylistModal({
} finally {
setLoading(false);
}
}, [searchQuery, page]);
}, [debouncedSearchQuery, page]);
// Effectuer la recherche quand la query change (avec debounce)
// Effectuer la recherche quand la query debounced change
useEffect(() => {
const timeoutId = setTimeout(() => {
if (searchQuery.trim() || open) {
performSearch();
} else {
setTracks([]);
setTotal(0);
}
}, 500);
return () => clearTimeout(timeoutId);
}, [searchQuery, open, performSearch]);
if (debouncedSearchQuery.trim() || open) {
performSearch();
} else {
setTracks([]);
setTotal(0);
}
}, [debouncedSearchQuery, open, performSearch]);
// Réinitialiser quand le modal s'ouvre
useEffect(() => {