Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(VirtualizedList)!: remove numberOfElementsVisibleOnScreen and numberOfElementsRendered props #153

Merged
merged 12 commits into from
Oct 8, 2024
Merged
9 changes: 3 additions & 6 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,7 @@ It also ensures that the scroll event is propagated properly to parent ScrollVie
| `data` | `Array<T>` | The array of data items to render. ⚠️ You should memoize this array for maximum performance. A costly memo depends on it. |
| `renderItem` | `(args: { item: T }) => JSX.Element` | A function that returns the JSX element to render for each item in the data array. The function receives an object with the item as a parameter. |
| `itemSize` | `number \| ((item: T) => number)` | In case you specify a number it will behave like this : ff vertical, the height of an item; otherwise, the width. You can also specify a function which needs to return for each item of `data` its size in pixel in order for the list to handle various item sizes. ⚠️ You should memoize this function for maximal performances. An important memo depends on it. |
| `numberOfRenderedItems` | `number` | The number of items to be rendered (virtualization size). ⚠️ It must be at least equal to `numberOfItemsVisibleOnScreen +2` or when using jump-on-scroll : `(2 * numberOfItemsVisibleOnScreen) + 1` to ensure correct rendering. |
| `numberOfItemsVisibleOnScreen` | `number` | The number of items visible on the screen. This helps determine how to slice the data and when to stop the scroll at the end of the list. |
| `additionalItemsRendered` | `number` | Optional : The number of items to be rendered (virtualization size) additionally to the elements visible on screen. Base value is 4 for `stick-to-start` and `stick-to-end` scrolls, and twice the number of elements visible for `jump-on-scroll`. |
| `onEndReached` | `() => void` | An optional callback function that is called when the user reaches the end of the list. Helps with pagination. |
| `onEndReachedThresholdItemsNumber` | `number` | The number of items left to display before triggering the `onEndReached` callback. Defaults to 3. |
| `style` | `ViewStyle` | Custom style to be applied to the VirtualizedList container. |
Expand Down Expand Up @@ -319,10 +318,9 @@ VirtualizedGrids only support vertical orientation (vertically scrollable), but
| `renderItem` | `(args: { item: T }) => JSX.Element` | A function that returns the JSX element to render for each item in the data array. The function receives an object with the item as a parameter. |
| `numberOfColumns` | `Number` | The number of columns in the grid or the number of items per row. |
| `itemHeight` | `Number` | The height of each item in the grid. |
| `numberOfRenderedRows` | `Number` | How many rows are rendered (virtualization size). |
| `additionalRenderedRows` | `Number` | Optional : The number of rows to be rendered (virtualization size) additionally to the rows visible on screen. Base value is 4 for `stick-to-start` and `stick-to-end` scrolls, and twice the number of elements visible for `jump-on-scroll`. |
| `header` | `JSX.Element` | Optional header component you can provide to display at the top of a virtualized grid. If provided, you also need to provide its size (so that the grid knows how to scroll) |
| `headerSize` | `Number` | The Size in pixels of the (optionnally) provided header. |
| `numberOfRowsVisibleOnScreen` | `Number` | How many rows are visible on the screen (helps with knowing how to slice the data and stop the scroll at the end of the list). |
| `onEndReached` | `() => void` | An optional callback function that is called when the user reaches the end of the list. Helps with pagination. |
| `onEndReachedThresholdRowsNumber` | `Number` | Number of rows left to display before triggering the onEndReached event. |
| `style` | `Object` | Used to modify the style of the grid. |
Expand Down Expand Up @@ -354,8 +352,7 @@ const renderItem = ({ item }) => {
renderItem={renderItem}
numberOfColumns={3}
itemHeight={100}
numberOfRenderedRows={7}
numberOfRowsVisibleOnScreen={3}
additionalItemsRendered={5}
onEndReachedThresholdRowsNumber={2}
rowContainerStyle={{gap: 15}}
/>
Expand Down
4 changes: 0 additions & 4 deletions packages/example/src/components/VirtualizedSpatialGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import { Header } from '../modules/header/view/Header';
import { BottomArrow, TopArrow } from '../design-system/components/Arrows';
import { ProgramInfo } from '../modules/program/domain/programInfo';

const NUMBER_OF_ROWS_VISIBLE_ON_SCREEN = 2;
const NUMBER_OF_RENDERED_ROWS = NUMBER_OF_ROWS_VISIBLE_ON_SCREEN + 5;
const NUMBER_OF_COLUMNS = 7;
const INFINITE_SCROLL_ROW_THRESHOLD = 2;

Expand Down Expand Up @@ -44,8 +42,6 @@ export const VirtualizedSpatialGrid = ({ containerStyle }: { containerStyle?: Vi
renderItem={renderItem}
itemHeight={theme.sizes.program.portrait.height * 1.1}
numberOfColumns={NUMBER_OF_COLUMNS}
numberOfRenderedRows={NUMBER_OF_RENDERED_ROWS}
numberOfRowsVisibleOnScreen={NUMBER_OF_ROWS_VISIBLE_ON_SCREEN}
onEndReachedThresholdRowsNumber={INFINITE_SCROLL_ROW_THRESHOLD}
rowContainerStyle={styles.rowStyle}
ascendingArrow={<BottomArrow />}
Expand Down
3 changes: 0 additions & 3 deletions packages/example/src/modules/program/view/ProgramList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import { useKey } from '../../../hooks/useKey';
import React from 'react';

const NUMBER_OF_ITEMS_VISIBLE_ON_SCREEN = 7;
const WINDOW_SIZE = NUMBER_OF_ITEMS_VISIBLE_ON_SCREEN + 8;
const ROW_PADDING = scaledPixels(70);

const GAP_BETWEEN_ELEMENTS = scaledPixels(30);
Expand Down Expand Up @@ -101,8 +100,6 @@ export const ProgramList = React.forwardRef<View, ProgramListProps>(
data={programInfos}
renderItem={renderItem}
itemSize={itemSize}
numberOfRenderedItems={WINDOW_SIZE}
numberOfItemsVisibleOnScreen={NUMBER_OF_ITEMS_VISIBLE_ON_SCREEN}
onEndReachedThresholdItemsNumber={NUMBER_OF_ITEMS_VISIBLE_ON_SCREEN}
// @ts-expect-error TODO change the type from ReactElement to ReactNode in the core
descendingArrow={isActive ? <LeftArrow /> : null}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,8 @@ describe('SpatialNavigationVirtualizedGrid', () => {
<DefaultFocus>
<SpatialNavigationVirtualizedGrid
renderItem={renderItem}
data={createDataArray(19)}
data={createDataArray(28)}
itemHeight={100}
numberOfRenderedRows={5}
numberOfRowsVisibleOnScreen={3}
numberOfColumns={3}
testID="test-grid"
/>
Expand All @@ -56,7 +54,7 @@ describe('SpatialNavigationVirtualizedGrid', () => {
expect(screen).toMatchSnapshot();

const listElement = component.getByTestId(gridTestId);
expect(listElement).toHaveStyle({ height: 700 });
expect(listElement).toHaveStyle({ height: 1000 });

expect(screen.getByText('button 1')).toBeTruthy();
expectButtonToHaveFocus(component, 'button 1');
Expand All @@ -74,7 +72,13 @@ describe('SpatialNavigationVirtualizedGrid', () => {
expect(screen.getByText('button 13')).toBeTruthy();
expect(screen.getByText('button 14')).toBeTruthy();
expect(screen.getByText('button 15')).toBeTruthy();
expect(screen.queryByText('button 16')).toBeFalsy();
expect(screen.getByText('button 16')).toBeTruthy();
expect(screen.getByText('button 17')).toBeTruthy();
expect(screen.getByText('button 18')).toBeTruthy();
expect(screen.getByText('button 19')).toBeTruthy();
expect(screen.getByText('button 20')).toBeTruthy();
expect(screen.getByText('button 21')).toBeTruthy();
expect(screen.queryByText('button 22')).toBeFalsy();
});

it('handles correctly RIGHT & DOWN and RENDERS new elements accordingly while deleting elements that are too far from scroll when on stick to start scroll', () => {
Expand All @@ -84,7 +88,7 @@ describe('SpatialNavigationVirtualizedGrid', () => {

const listElement = component.getByTestId(gridTestId);
expectListToHaveScroll(listElement, 0);
expect(listElement).toHaveStyle({ height: 700 });
expect(listElement).toHaveStyle({ height: 1000 });

testRemoteControlManager.handleRight();

Expand All @@ -104,70 +108,69 @@ describe('SpatialNavigationVirtualizedGrid', () => {
expect(screen.getByText('button 13')).toBeTruthy();
expect(screen.getByText('button 14')).toBeTruthy();
expect(screen.getByText('button 15')).toBeTruthy();
expect(screen.queryByText('button 16')).toBeFalsy();
expect(screen.getByText('button 16')).toBeTruthy();
expect(screen.getByText('button 17')).toBeTruthy();
expect(screen.getByText('button 18')).toBeTruthy();
expect(screen.getByText('button 19')).toBeTruthy();
expect(screen.getByText('button 20')).toBeTruthy();
expect(screen.getByText('button 21')).toBeTruthy();
expect(screen.queryByText('button 22')).toBeFalsy();

testRemoteControlManager.handleDown();
expectListToHaveScroll(listElement, -100);

expect(screen.getByText('button 1')).toBeTruthy();
expect(screen.getByText('button 2')).toBeTruthy();
expect(screen.getByText('button 3')).toBeTruthy();
expect(screen.getByText('button 4')).toBeTruthy();
expect(screen.getByText('button 5')).toBeTruthy();
expectButtonToHaveFocus(component, 'button 5');
expect(screen.getByText('button 6')).toBeTruthy();
expect(screen.getByText('button 7')).toBeTruthy();
expect(screen.getByText('button 8')).toBeTruthy();
expect(screen.getByText('button 9')).toBeTruthy();
expect(screen.getByText('button 10')).toBeTruthy();
expect(screen.getByText('button 11')).toBeTruthy();
expect(screen.getByText('button 12')).toBeTruthy();
expect(screen.getByText('button 13')).toBeTruthy();
expect(screen.getByText('button 14')).toBeTruthy();
expect(screen.getByText('button 15')).toBeTruthy();
expect(screen.queryByText('button 16')).toBeFalsy();

testRemoteControlManager.handleDown();
expectListToHaveScroll(listElement, -200);
expectButtonToHaveFocus(component, 'button 8');

testRemoteControlManager.handleDown();
expectListToHaveScroll(listElement, -300);
expectButtonToHaveFocus(component, 'button 11');

expect(screen.queryByText('button 1')).toBeFalsy();
expect(screen.queryByText('button 2')).toBeFalsy();
expect(screen.queryByText('button 3')).toBeFalsy();
expect(screen.getByText('button 4')).toBeTruthy();
expect(screen.getByText('button 5')).toBeTruthy();
expect(screen.getByText('button 6')).toBeTruthy();

testRemoteControlManager.handleDown();
expectListToHaveScroll(listElement, -400);
expectButtonToHaveFocus(component, 'button 14');

expect(screen.queryByText('button 4')).toBeFalsy();
expect(screen.queryByText('button 5')).toBeFalsy();
expect(screen.queryByText('button 6')).toBeFalsy();
expect(screen.getByText('button 7')).toBeTruthy();
expect(screen.getByText('button 8')).toBeTruthy();
expectButtonToHaveFocus(component, 'button 8');
expect(screen.getByText('button 9')).toBeTruthy();
expect(screen.getByText('button 10')).toBeTruthy();
expect(screen.getByText('button 11')).toBeTruthy();
expect(screen.getByText('button 12')).toBeTruthy();
expect(screen.getByText('button 13')).toBeTruthy();
expect(screen.getByText('button 14')).toBeTruthy();
expect(screen.getByText('button 15')).toBeTruthy();
expect(screen.getByText('button 16')).toBeTruthy();
expect(screen.getByText('button 17')).toBeTruthy();
expect(screen.getByText('button 18')).toBeTruthy();
expect(screen.queryByText('button 19')).toBeFalsy();

expect(screen).toMatchSnapshot();
testRemoteControlManager.handleDown();
expectListToHaveScroll(listElement, -500);
expectButtonToHaveFocus(component, 'button 17');

expect(screen.queryByText('button 7')).toBeFalsy();
expect(screen.queryByText('button 8')).toBeFalsy();
expect(screen.queryByText('button 9')).toBeFalsy();
expect(screen.getByText('button 10')).toBeTruthy();

testRemoteControlManager.handleDown();
expectListToHaveScroll(listElement, -300);
expectButtonToHaveFocus(component, 'button 11');
expectListToHaveScroll(listElement, -600);
expectButtonToHaveFocus(component, 'button 20');

expect(screen.queryByText('button 7')).toBeFalsy();
expect(screen.queryByText('button 8')).toBeFalsy();
expect(screen.queryByText('button 9')).toBeFalsy();
expect(screen.getByText('button 10')).toBeTruthy();

testRemoteControlManager.handleDown();
expectListToHaveScroll(listElement, -400);
expectButtonToHaveFocus(component, 'button 14');
expectListToHaveScroll(listElement, -700);
expectButtonToHaveFocus(component, 'button 23');

testRemoteControlManager.handleDown();
expectListToHaveScroll(listElement, -400);
expectButtonToHaveFocus(component, 'button 17');
expectListToHaveScroll(listElement, -700);
expectButtonToHaveFocus(component, 'button 26');

testRemoteControlManager.handleDown();
expectListToHaveScroll(listElement, -400);
expectButtonToHaveFocus(component, 'button 19');
expectListToHaveScroll(listElement, -700);
expectButtonToHaveFocus(component, 'button 28');
});

it('handles correctly RIGHT & DOWN and RENDERS new elements accordingly while deleting elements that are too far from scroll when on stick to end scroll', () => {
Expand All @@ -178,8 +181,6 @@ describe('SpatialNavigationVirtualizedGrid', () => {
renderItem={renderItem}
data={createDataArray(19)}
itemHeight={100}
numberOfRenderedRows={5}
numberOfRowsVisibleOnScreen={3}
numberOfColumns={3}
testID="test-grid"
scrollBehavior="stick-to-end"
Expand Down Expand Up @@ -231,8 +232,6 @@ describe('SpatialNavigationVirtualizedGrid', () => {
renderItem={renderItem}
data={createDataArray(19)}
itemHeight={100}
numberOfRenderedRows={7}
numberOfRowsVisibleOnScreen={3}
numberOfColumns={3}
testID="test-grid"
scrollBehavior="jump-on-scroll"
Expand Down
Loading
Loading