Skip to content

Commit ce77524

Browse files
MelvinBotmkhutornyi
andcommitted
Clear initiallyFocusedItemKey after first render to prevent FlashList auto-scroll
FlashList internally auto-scrolls when initialScrollIndex changes from -1 to a valid index. This happens when search is cleared and the focused item key transitions from "not found" to "found" in the data. Using a ref to track post-mount state ensures the key is only passed on the initial render. Co-authored-by: mkhutornyi <mkhutornyi@users.noreply.github.com>
1 parent 5e2028b commit ce77524

1 file changed

Lines changed: 11 additions & 2 deletions

File tree

src/components/Search/SearchMultipleSelectionPicker.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, {useState} from 'react';
1+
import React, {useEffect, useRef, useState} from 'react';
22
import MultiSelectListItem from '@components/SelectionList/ListItem/MultiSelectListItem';
33
import SelectionListWithSections from '@components/SelectionList/SelectionListWithSections';
44
import useDebouncedState from '@hooks/useDebouncedState';
@@ -35,7 +35,7 @@ function SearchMultipleSelectionPicker<T extends string | string[]>({
3535

3636
const [initialSelectedIDs] = useState(() => new Set((initiallySelectedItems ?? []).map((item) => item.value.toString())));
3737
const [selectedItemIDs, setSelectedItemIDs] = useState(() => initialSelectedIDs);
38-
const [initiallyFocusedKey] = useState(() => {
38+
const [initiallyFocusedKeyComputed] = useState(() => {
3939
let minItem: SearchMultipleSelectionPickerItem<T> | undefined;
4040
for (const item of items) {
4141
if (initialSelectedIDs.has(item.value.toString())) {
@@ -47,6 +47,15 @@ function SearchMultipleSelectionPicker<T extends string | string[]>({
4747
return minItem?.name;
4848
});
4949

50+
// Clear after first render to prevent FlashList from auto-scrolling when data changes
51+
// cause the key to transition from "not found" to "found" (e.g., clearing a search).
52+
const initialFocusAppliedRef = useRef(false);
53+
useEffect(() => {
54+
initialFocusAppliedRef.current = true;
55+
}, []);
56+
// eslint-disable-next-line react-hooks/refs -- Reading ref to detect post-mount state; intentional one-time prop pattern
57+
const initiallyFocusedKey = initialFocusAppliedRef.current ? undefined : initiallyFocusedKeyComputed;
58+
5059
const searchLower = debouncedSearchTerm.toLowerCase();
5160
const sectionData: Array<{text: string; keyForList: string; isSelected: boolean; value: T; leftElement?: React.ReactNode}> = [];
5261
for (const item of items) {

0 commit comments

Comments
 (0)