Skip to content
17 changes: 12 additions & 5 deletions src/components/SelectionListWithModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import useHandleSelectionMode from '@hooks/useHandleSelectionMode';
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import useMobileSelectionMode from '@hooks/useMobileSelectionMode';
import useNetwork from '@hooks/useNetwork';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import {turnOnMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
import CONST from '@src/CONST';
Expand All @@ -33,27 +34,33 @@ function SelectionListWithModal<TItem extends ListItem>({
const [isModalVisible, setIsModalVisible] = useState(false);
const [longPressedItem, setLongPressedItem] = useState<TItem | null>(null);
const {translate} = useLocalize();
const {isOffline} = useNetwork();
// We need to use isSmallScreenWidth instead of shouldUseNarrowLayout here because there is a race condition that causes shouldUseNarrowLayout to change indefinitely in this component
// See https://github.com/Expensify/App/issues/48675 for more details
// eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth
const {isSmallScreenWidth} = useResponsiveLayout();
const isFocused = useIsFocused();
const icons = useMemoizedLazyExpensifyIcons(['CheckSquare'] as const);

// Filter out the pending delete item when online to prevent making multiple updates to debouncedData which causes the deleted item is shown again
const filteredData = useMemo(() => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coming from #81658, we should filter out the pending delete items without errors

return data.filter((item) => item.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || isOffline);
}, [data, isOffline]);

const isMobileSelectionModeEnabled = useMobileSelectionMode();

// Debounce the data prop to prevent rapid updates that cause FlashList layout errors
// This gives FlashList time to properly update its layout cache when searching/filtering
const [, debouncedData, setDataState] = useDebouncedState<TItem[]>(data, CONST.TIMING.SEARCH_OPTION_LIST_DEBOUNCE_TIME);
const [, debouncedData, setDataState] = useDebouncedState<TItem[]>(filteredData, CONST.TIMING.SEARCH_OPTION_LIST_DEBOUNCE_TIME);

// Determine if this is changed by filtering (to limit multiple rerenders)
const isFiltering = data.length < debouncedData.length;
const isFiltering = filteredData.length < debouncedData.length;

useEffect(() => {
setDataState(data);
}, [data, setDataState]);
setDataState(filteredData);
}, [filteredData, setDataState]);

const displayData = isFiltering ? debouncedData : data;
const displayData = isFiltering ? debouncedData : filteredData;

const selectedItems = useMemo(
() =>
Expand Down
Loading