Skip to content

Commit

Permalink
Merge pull request #37627 from lukemorawski/36121-improvement-enable_…
Browse files Browse the repository at this point in the history
…pagination_on_selectionlist

Adding pagination to SelectionList component
  • Loading branch information
cristipaval authored Mar 12, 2024
2 parents 6646917 + 1ba195b commit 0dc2151
Showing 1 changed file with 36 additions and 1 deletion.
37 changes: 36 additions & 1 deletion src/components/SelectionList/BaseSelectionList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {useFocusEffect, useIsFocused} from '@react-navigation/native';
import isEmpty from 'lodash/isEmpty';
import type {ForwardedRef} from 'react';
import React, {forwardRef, useCallback, useEffect, useMemo, useRef, useState} from 'react';
import type {LayoutChangeEvent, SectionList as RNSectionList, TextInput as RNTextInput, SectionListRenderItemInfo} from 'react-native';
Expand All @@ -10,6 +11,7 @@ import FixedFooter from '@components/FixedFooter';
import OptionsListSkeletonView from '@components/OptionsListSkeletonView';
import SafeAreaConsumer from '@components/SafeAreaConsumer';
import SectionList from '@components/SectionList';
import ShowMoreButton from '@components/ShowMoreButton';
import Text from '@components/Text';
import TextInput from '@components/TextInput';
import useActiveElementRole from '@hooks/useActiveElementRole';
Expand Down Expand Up @@ -78,6 +80,9 @@ function BaseSelectionList<TItem extends ListItem>(
const isFocused = useIsFocused();
const [maxToRenderPerBatch, setMaxToRenderPerBatch] = useState(shouldUseDynamicMaxToRenderPerBatch ? 0 : CONST.MAX_TO_RENDER_PER_BATCH.DEFAULT);
const [isInitialSectionListRender, setIsInitialSectionListRender] = useState(true);
const [currentPage, setCurrentPage] = useState(1);

const incrementPage = () => setCurrentPage((prev) => prev + 1);

/**
* Iterates through the sections and items inside each section, and builds 3 arrays along the way:
Expand Down Expand Up @@ -153,6 +158,33 @@ function BaseSelectionList<TItem extends ListItem>(
// If `initiallyFocusedOptionKey` is not passed, we fall back to `-1`, to avoid showing the highlight on the first member
const [focusedIndex, setFocusedIndex] = useState(() => flattenedSections.allOptions.findIndex((option) => option.keyForList === initiallyFocusedOptionKey));

const [slicedSections, ShowMoreButtonInstance] = useMemo(
() => [
sections.map((section) => {
if (isEmpty(section.data)) {
return section;
}

return {
...section,
data: section.data.slice(0, CONST.MAX_OPTIONS_SELECTOR_PAGE_LENGTH * currentPage),
};
}),
flattenedSections.allOptions.length > CONST.MAX_OPTIONS_SELECTOR_PAGE_LENGTH * currentPage ? (
<ShowMoreButton
containerStyle={[styles.mt2, styles.mb5]}
currentCount={CONST.MAX_OPTIONS_SELECTOR_PAGE_LENGTH * currentPage}
totalCount={flattenedSections.allOptions.length}
onPress={incrementPage}
/>
) : null,
],
// we don't need to add styles here as they change
// we don't need to add flattendedSections here as they will change along with sections
// eslint-disable-next-line react-hooks/exhaustive-deps
[sections, currentPage],
);

// Disable `Enter` shortcut if the active element is a button or checkbox
const disableEnterShortcut = activeElementRole && [CONST.ROLE.BUTTON, CONST.ROLE.CHECKBOX].includes(activeElementRole as ButtonOrCheckBoxRoles);

Expand Down Expand Up @@ -361,6 +393,8 @@ function BaseSelectionList<TItem extends ListItem>(
}
// Remove the focus if the search input is empty else focus on the first non disabled item
const newSelectedIndex = textInputValue === '' ? -1 : 0;
// reseting the currrent page to 1 when the user types something
setCurrentPage(1);

updateAndScrollToFocusedIndex(newSelectedIndex);
}, [canSelectMultiple, flattenedSections.allOptions.length, prevTextInputValue, textInputValue, updateAndScrollToFocusedIndex]);
Expand Down Expand Up @@ -450,7 +484,7 @@ function BaseSelectionList<TItem extends ListItem>(
{!headerMessage && !canSelectMultiple && customListHeader}
<SectionList
ref={listRef}
sections={sections}
sections={slicedSections}
stickySectionHeadersEnabled={false}
renderSectionHeader={renderSectionHeader}
renderItem={renderItem}
Expand All @@ -469,6 +503,7 @@ function BaseSelectionList<TItem extends ListItem>(
testID="selection-list"
onLayout={onSectionListLayout}
style={(!maxToRenderPerBatch || isInitialSectionListRender) && styles.opacity0}
ListFooterComponent={ShowMoreButtonInstance}
/>
{children}
</>
Expand Down

0 comments on commit 0dc2151

Please sign in to comment.