Skip to content

Commit 474cc0a

Browse files
authored
Merge pull request Expensify#65806 from linhvovan29546/fix/62202-cards-not-arranged-on-refresh-page
fix: cards are not sorted after page refresh
2 parents b7ca122 + 13f89bd commit 474cc0a

2 files changed

Lines changed: 18 additions & 4 deletions

File tree

src/hooks/useSearchResults.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,29 @@ import usePrevious from './usePrevious';
88
* It utilizes `useTransition` to allow the searchQuery to change rapidly, while more expensive renders that occur using
99
* the result of the filtering and sorting are de-prioritized, allowing them to happen in the background.
1010
*/
11-
function useSearchResults<TValue extends ListItem>(data: TValue[], filterData: (datum: TValue, searchInput: string) => boolean, sortData: (data: TValue[]) => TValue[] = (d) => d) {
11+
function useSearchResults<TValue extends ListItem>(
12+
data: TValue[],
13+
filterData: (datum: TValue, searchInput: string) => boolean,
14+
sortData: (data: TValue[]) => TValue[] = (d) => d,
15+
/**
16+
* Whether to sort data immediately on mount to prevent briefly displaying unsorted data,
17+
* since sorting is handled inside startTransition.
18+
*/
19+
shouldSortInitialData?: boolean,
20+
) {
1221
const [inputValue, setInputValue] = useState('');
13-
const [result, setResult] = useState(data);
22+
const [result, setResult] = useState(() => (shouldSortInitialData ? sortData(data) : data));
1423
const prevData = usePrevious(data);
1524
const [, startTransition] = useTransition();
1625
useEffect(() => {
1726
startTransition(() => {
1827
const normalizedSearchQuery = inputValue.trim().toLowerCase();
19-
const filtered = normalizedSearchQuery.length ? data.filter((item) => filterData(item, normalizedSearchQuery)) : data;
28+
29+
// Create shallow copy of data to prevent mutation. When no search query exists, we pass the full dataset
30+
// to sortData. If sortData uses Array.sort() (which sorts in place and returns the same reference),
31+
// the original data array would be mutated. This breaks React's reference equality check in setResult,
32+
// preventing re-renders even when the sort order changes (e.g., on page refresh).
33+
const filtered = normalizedSearchQuery.length ? data.filter((item) => filterData(item, normalizedSearchQuery)) : [...data];
2034
const sorted = sortData(filtered);
2135
setResult(sorted);
2236
});

src/pages/workspace/companyCards/WorkspaceCompanyCardsList.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ function WorkspaceCompanyCardsList({cardsList, policyID, handleAssignCard, isDis
5252

5353
const filterCard = useCallback((card: Card, searchInput: string) => filterCardsByPersonalDetails(card, searchInput, personalDetails), [personalDetails]);
5454
const sortCards = useCallback((cards: Card[]) => sortCardsByCardholderName(cards, personalDetails), [personalDetails]);
55-
const [inputValue, setInputValue, filteredSortedCards] = useSearchResults(allCards, filterCard, sortCards);
55+
const [inputValue, setInputValue, filteredSortedCards] = useSearchResults(allCards, filterCard, sortCards, true);
5656

5757
const renderItem = useCallback(
5858
({item, index}: ListRenderItemInfo<Card>) => {

0 commit comments

Comments
 (0)