diff --git a/src/hooks/useSearchResults.ts b/src/hooks/useSearchResults.ts index 50b0366c70e7..fad21102b49e 100644 --- a/src/hooks/useSearchResults.ts +++ b/src/hooks/useSearchResults.ts @@ -8,15 +8,29 @@ import usePrevious from './usePrevious'; * It utilizes `useTransition` to allow the searchQuery to change rapidly, while more expensive renders that occur using * the result of the filtering and sorting are de-prioritized, allowing them to happen in the background. */ -function useSearchResults(data: TValue[], filterData: (datum: TValue, searchInput: string) => boolean, sortData: (data: TValue[]) => TValue[] = (d) => d) { +function useSearchResults( + data: TValue[], + filterData: (datum: TValue, searchInput: string) => boolean, + sortData: (data: TValue[]) => TValue[] = (d) => d, + /** + * Whether to sort data immediately on mount to prevent briefly displaying unsorted data, + * since sorting is handled inside startTransition. + */ + shouldSortInitialData?: boolean, +) { const [inputValue, setInputValue] = useState(''); - const [result, setResult] = useState(data); + const [result, setResult] = useState(() => (shouldSortInitialData ? sortData(data) : data)); const prevData = usePrevious(data); const [, startTransition] = useTransition(); useEffect(() => { startTransition(() => { const normalizedSearchQuery = inputValue.trim().toLowerCase(); - const filtered = normalizedSearchQuery.length ? data.filter((item) => filterData(item, normalizedSearchQuery)) : data; + + // Create shallow copy of data to prevent mutation. When no search query exists, we pass the full dataset + // to sortData. If sortData uses Array.sort() (which sorts in place and returns the same reference), + // the original data array would be mutated. This breaks React's reference equality check in setResult, + // preventing re-renders even when the sort order changes (e.g., on page refresh). + const filtered = normalizedSearchQuery.length ? data.filter((item) => filterData(item, normalizedSearchQuery)) : [...data]; const sorted = sortData(filtered); setResult(sorted); }); diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx index d9cd87fa2750..181c8944428c 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx @@ -52,7 +52,7 @@ function WorkspaceCompanyCardsList({cardsList, policyID, handleAssignCard, isDis const filterCard = useCallback((card: Card, searchInput: string) => filterCardsByPersonalDetails(card, searchInput, personalDetails), [personalDetails]); const sortCards = useCallback((cards: Card[]) => sortCardsByCardholderName(cards, personalDetails), [personalDetails]); - const [inputValue, setInputValue, filteredSortedCards] = useSearchResults(allCards, filterCard, sortCards); + const [inputValue, setInputValue, filteredSortedCards] = useSearchResults(allCards, filterCard, sortCards, true); const renderItem = useCallback( ({item, index}: ListRenderItemInfo) => {