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:
parent
8f93d2d5b4
commit
f4b8a5be6e
3 changed files with 93 additions and 16 deletions
|
|
@ -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
|
||||
|
|
|
|||
78
apps/web/docs/SEARCH_DEBOUNCE_AUDIT.md
Normal file
78
apps/web/docs/SEARCH_DEBOUNCE_AUDIT.md
Normal 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)
|
||||
|
|
@ -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(() => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue