Skip to content

Commit a8a9b45

Browse files
committed
Add useEffect to manage scrolling
1 parent a1a7870 commit a8a9b45

2 files changed

Lines changed: 48 additions & 7 deletions

File tree

src/components/SelectionList/BaseSelectionList.tsx

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager';
1212
import useDebounce from '@hooks/useDebounce';
1313
import useKeyboardShortcut from '@hooks/useKeyboardShortcut';
1414
import useKeyboardState from '@hooks/useKeyboardState';
15+
import usePrevious from '@hooks/usePrevious';
1516
import useSafeAreaPaddings from '@hooks/useSafeAreaPaddings';
1617
import useScrollEnabled from '@hooks/useScrollEnabled';
1718
import useSingleExecution from '@hooks/useSingleExecution';
@@ -288,7 +289,6 @@ function BaseSelectionList<TItem extends ListItem>({
288289
onFocusChange={(v: boolean) => (isTextInputFocusedRef.current = v)}
289290
showLoadingPlaceholder={showLoadingPlaceholder}
290291
isLoadingNewOptions={isLoadingNewOptions}
291-
setFocusedIndex={setFocusedIndex}
292292
/>
293293
);
294294
};
@@ -392,6 +392,52 @@ function BaseSelectionList<TItem extends ListItem>({
392392
[data.length, scrollToIndex, setFocusedIndex],
393393
);
394394

395+
const prevSearchValue = usePrevious(textInputOptions?.value);
396+
const prevSelectedOptionsLength = usePrevious(dataDetails.selectedOptions.length);
397+
const prevAllOptionsLength = usePrevious(data.length);
398+
399+
useEffect(() => {
400+
const currentSearchValue = textInputOptions?.value;
401+
const searchChanged = prevSearchValue !== currentSearchValue;
402+
const selectedOptionsChanged = dataDetails.selectedOptions.length !== prevSelectedOptionsLength;
403+
// Focus shouldn't be changed if: input value is the same or data length is 0
404+
// shouldUpdateFocusedIndex is true => other function handles the focus
405+
if ((!searchChanged && !selectedOptionsChanged) || data.length === 0 || shouldUpdateFocusedIndex) {
406+
return;
407+
}
408+
409+
// Clearing search
410+
if (prevSearchValue && !currentSearchValue) {
411+
const foundSelectedItemIndex = data.findIndex(isItemSelected);
412+
413+
if (foundSelectedItemIndex !== -1 && !canSelectMultiple) {
414+
scrollToIndex(foundSelectedItemIndex);
415+
setFocusedIndex(foundSelectedItemIndex);
416+
return;
417+
}
418+
}
419+
420+
// Remove focus (-1) if the search is idle or if the user is just toggling options without changing the list content
421+
// Otherwise (e.g. when filtering/typing), focus on the first item (0)
422+
const isSearchIdle = !prevSearchValue && !currentSearchValue;
423+
const newSelectedIndex = isSearchIdle || (selectedOptionsChanged && prevAllOptionsLength === data.length) ? -1 : 0;
424+
425+
scrollToIndex(newSelectedIndex);
426+
setFocusedIndex(newSelectedIndex);
427+
}, [
428+
canSelectMultiple,
429+
data,
430+
dataDetails.selectedOptions.length,
431+
isItemSelected,
432+
prevAllOptionsLength,
433+
prevSelectedOptionsLength,
434+
prevSearchValue,
435+
scrollToIndex,
436+
setFocusedIndex,
437+
shouldUpdateFocusedIndex,
438+
textInputOptions?.value,
439+
]);
440+
395441
useEffect(() => {
396442
if (!itemFocusTimeoutRef.current) {
397443
return;

src/components/SelectionList/components/TextInput.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@ type TextInputProps = {
4545
/** Whether to show the loading indicator for new options */
4646
isLoadingNewOptions?: boolean;
4747

48-
/** Function to update the focused index in the list */
49-
setFocusedIndex: (index: number) => void;
50-
5148
/** Function to focus text input component */
5249
focusTextInput: () => void;
5350
};
@@ -64,7 +61,6 @@ function TextInput({
6461
showLoadingPlaceholder,
6562
isLoadingNewOptions,
6663
shouldShowTextInput,
67-
setFocusedIndex,
6864
focusTextInput,
6965
}: TextInputProps) {
7066
const styles = useThemeStyles();
@@ -80,9 +76,8 @@ function TextInput({
8076
const handleTextInputChange = useCallback(
8177
(text: string) => {
8278
onChangeText?.(text);
83-
setFocusedIndex(0);
8479
},
85-
[onChangeText, setFocusedIndex],
80+
[onChangeText],
8681
);
8782

8883
useFocusEffect(

0 commit comments

Comments
 (0)