From c2764b6d6c4ccd4b2f3cfef96c399479118fba19 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Mon, 15 Sep 2025 10:58:02 +0200 Subject: [PATCH 1/3] move itemHeights as ref --- .../SelectionList/BaseSelectionList.tsx | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 6fe6451d38fc..a604de9c6d84 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -191,7 +191,7 @@ function BaseSelectionList({ const [currentPage, setCurrentPage] = useState(() => calculateInitialCurrentPage()); const isTextInputFocusedRef = useRef(false); const {singleExecution} = useSingleExecution(); - const [itemHeights, setItemHeights] = useState>({}); + const itemHeights = useRef>({}); const pendingScrollIndexRef = useRef(null); const onItemLayout = (event: LayoutChangeEvent, itemKey: string | null | undefined) => { @@ -200,11 +200,10 @@ function BaseSelectionList({ } const {height} = event.nativeEvent.layout; - - setItemHeights((prevHeights) => ({ - ...prevHeights, + itemHeights.current = { + ...itemHeights.current, [itemKey]: height, - })); + }; }; const canShowProductTrainingTooltipMemo = useMemo(() => { @@ -220,6 +219,7 @@ function BaseSelectionList({ * so we can calculate the position of any given item when scrolling programmatically */ const flattenedSections = useMemo>(() => { + const time = performance.now(); const allOptions: TItem[] = []; const disabledOptionsIndexes: number[] = []; @@ -257,7 +257,7 @@ function BaseSelectionList({ disabledIndex += 1; // Account for the height of the item in getItemLayout - const fullItemHeight = item?.keyForList && itemHeights[item.keyForList] ? itemHeights[item.keyForList] : getItemHeight(item); + const fullItemHeight = item?.keyForList && itemHeights.current[item.keyForList] ? itemHeights.current[item.keyForList] : getItemHeight(item); itemLayouts.push({length: fullItemHeight, offset}); offset += fullItemHeight; @@ -281,7 +281,6 @@ function BaseSelectionList({ ); } const totalSelectable = allOptions.length - disabledOptionsIndexes.length; - return { allOptions, selectedOptions, @@ -291,7 +290,7 @@ function BaseSelectionList({ allSelected: selectedOptions.length > 0 && selectedOptions.length === totalSelectable, someSelected: selectedOptions.length > 0 && selectedOptions.length < totalSelectable, }; - }, [customListHeader, customListHeaderHeight, sections, canSelectMultiple, isItemSelected, itemHeights, getItemHeight]); + }, [customListHeader, customListHeaderHeight, sections, canSelectMultiple, isItemSelected, getItemHeight]); const incrementPage = useCallback(() => { if (flattenedSections.allOptions.length <= CONST.MAX_SELECTION_LIST_PAGE_LENGTH * currentPage) { @@ -352,9 +351,9 @@ function BaseSelectionList({ // the top of the viewable area at all times by adjusting the viewOffset. if (shouldKeepFocusedItemAtTopOfViewableArea) { const firstPreviousItem = index > 0 ? flattenedSections.allOptions.at(index - 1) : undefined; - const firstPreviousItemHeight = firstPreviousItem && firstPreviousItem.keyForList ? itemHeights[firstPreviousItem.keyForList] : 0; + const firstPreviousItemHeight = firstPreviousItem && firstPreviousItem.keyForList ? itemHeights.current[firstPreviousItem.keyForList] : 0; const secondPreviousItem = index > 1 ? flattenedSections.allOptions.at(index - 2) : undefined; - const secondPreviousItemHeight = secondPreviousItem && secondPreviousItem?.keyForList ? itemHeights[secondPreviousItem.keyForList] : 0; + const secondPreviousItemHeight = secondPreviousItem && secondPreviousItem?.keyForList ? itemHeights.current[secondPreviousItem.keyForList] : 0; viewOffsetToKeepFocusedItemAtTopOfViewableArea = firstPreviousItemHeight + secondPreviousItemHeight; } From 4f0cc87c36a8faa6e46740f64980361fea7a1824 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Mon, 15 Sep 2025 11:40:14 +0200 Subject: [PATCH 2/3] use stable reference of selectedItems array default --- src/components/SelectionList/BaseSelectionList.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index a604de9c6d84..2c1f24f549c8 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -43,6 +43,7 @@ import FocusAwareCellRendererComponent from './FocusAwareCellRendererComponent'; import type {ButtonOrCheckBoxRoles, FlattenedSectionsReturn, ListItem, SectionListDataType, SectionWithIndexOffset, SelectionListProps} from './types'; const getDefaultItemHeight = () => variables.optionRowHeight; +const DEFAULT_SELECTED_ITEMS: string[] = []; function BaseSelectionList({ sections, @@ -144,7 +145,7 @@ function BaseSelectionList({ loaderSpeed, errorText, shouldUseDefaultRightHandSideCheckmark, - selectedItems = [], + selectedItems = DEFAULT_SELECTED_ITEMS, isSelected, canShowProductTrainingTooltip, renderScrollComponent, @@ -219,7 +220,6 @@ function BaseSelectionList({ * so we can calculate the position of any given item when scrolling programmatically */ const flattenedSections = useMemo>(() => { - const time = performance.now(); const allOptions: TItem[] = []; const disabledOptionsIndexes: number[] = []; From eee2eaca3923694d0e190fbc5b9cd4f85f9c6ce4 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Mon, 15 Sep 2025 13:55:59 +0200 Subject: [PATCH 3/3] use getEmptyArray --- src/components/SelectionList/BaseSelectionList.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 2c1f24f549c8..588a3462f62f 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -37,13 +37,13 @@ import Log from '@libs/Log'; import variables from '@styles/variables'; import CONST from '@src/CONST'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import getEmptyArray from '@src/types/utils/getEmptyArray'; import arraysEqual from '@src/utils/arraysEqual'; import BaseSelectionListItemRenderer from './BaseSelectionListItemRenderer'; import FocusAwareCellRendererComponent from './FocusAwareCellRendererComponent'; import type {ButtonOrCheckBoxRoles, FlattenedSectionsReturn, ListItem, SectionListDataType, SectionWithIndexOffset, SelectionListProps} from './types'; const getDefaultItemHeight = () => variables.optionRowHeight; -const DEFAULT_SELECTED_ITEMS: string[] = []; function BaseSelectionList({ sections, @@ -145,7 +145,7 @@ function BaseSelectionList({ loaderSpeed, errorText, shouldUseDefaultRightHandSideCheckmark, - selectedItems = DEFAULT_SELECTED_ITEMS, + selectedItems = getEmptyArray(), isSelected, canShowProductTrainingTooltip, renderScrollComponent,