diff --git a/Libraries/Lists/FillRateHelper.js b/Libraries/Lists/FillRateHelper.js index 1a13a1933b1..9327f465180 100644 --- a/Libraries/Lists/FillRateHelper.js +++ b/Libraries/Lists/FillRateHelper.js @@ -10,6 +10,8 @@ 'use strict'; +import type {FrameMetricProps} from './VirtualizedListProps'; + export type FillRateInfo = Info; class Info { @@ -49,7 +51,7 @@ let _sampleRate = DEBUG ? 1 : null; class FillRateHelper { _anyBlankStartTime = (null: ?number); _enabled = false; - _getFrameMetrics: (index: number) => ?FrameMetrics; + _getFrameMetrics: (index: number, props: FrameMetricProps) => ?FrameMetrics; _info = new Info(); _mostlyBlankStartTime = (null: ?number); _samplesStartTime = (null: ?number); @@ -77,7 +79,9 @@ class FillRateHelper { _minSampleCount = minSampleCount; } - constructor(getFrameMetrics: (index: number) => ?FrameMetrics) { + constructor( + getFrameMetrics: (index: number, props: FrameMetricProps) => ?FrameMetrics, + ) { this._getFrameMetrics = getFrameMetrics; this._enabled = (_sampleRate || 0) > Math.random(); this._resetData(); @@ -134,8 +138,7 @@ class FillRateHelper { computeBlankness( props: { - data: any, - getItemCount: (data: any) => number, + ...FrameMetricProps, initialNumToRender?: ?number, ... }, @@ -181,9 +184,9 @@ class FillRateHelper { let blankTop = 0; let first = state.first; - let firstFrame = this._getFrameMetrics(first); + let firstFrame = this._getFrameMetrics(first, props); while (first <= state.last && (!firstFrame || !firstFrame.inLayout)) { - firstFrame = this._getFrameMetrics(first); + firstFrame = this._getFrameMetrics(first, props); first++; } // Only count blankTop if we aren't rendering the first item, otherwise we will count the header @@ -196,9 +199,9 @@ class FillRateHelper { } let blankBottom = 0; let last = state.last; - let lastFrame = this._getFrameMetrics(last); + let lastFrame = this._getFrameMetrics(last, props); while (last >= state.first && (!lastFrame || !lastFrame.inLayout)) { - lastFrame = this._getFrameMetrics(last); + lastFrame = this._getFrameMetrics(last, props); last--; } // Only count blankBottom if we aren't rendering the last item, otherwise we will count the diff --git a/Libraries/Lists/ViewabilityHelper.js b/Libraries/Lists/ViewabilityHelper.js index ae91b25ab68..c70aa563620 100644 --- a/Libraries/Lists/ViewabilityHelper.js +++ b/Libraries/Lists/ViewabilityHelper.js @@ -10,6 +10,8 @@ 'use strict'; +import type {FrameMetricProps} from './VirtualizedListProps'; + const invariant = require('invariant'); export type ViewToken = { @@ -99,10 +101,13 @@ class ViewabilityHelper { * Determines which items are viewable based on the current metrics and config. */ computeViewableItems( - itemCount: number, + props: FrameMetricProps, scrollOffset: number, viewportHeight: number, - getFrameMetrics: (index: number) => ?{ + getFrameMetrics: ( + index: number, + props: FrameMetricProps, + ) => ?{ length: number, offset: number, ... @@ -114,6 +119,7 @@ class ViewabilityHelper { ... }, ): Array { + const itemCount = props.getItemCount(props.data); const {itemVisiblePercentThreshold, viewAreaCoveragePercentThreshold} = this._config; const viewAreaMode = viewAreaCoveragePercentThreshold != null; @@ -140,7 +146,7 @@ class ViewabilityHelper { return []; } for (let idx = first; idx <= last; idx++) { - const metrics = getFrameMetrics(idx); + const metrics = getFrameMetrics(idx, props); if (!metrics) { continue; } @@ -172,10 +178,13 @@ class ViewabilityHelper { * `onViewableItemsChanged` as appropriate. */ onUpdate( - itemCount: number, + props: FrameMetricProps, scrollOffset: number, viewportHeight: number, - getFrameMetrics: (index: number) => ?{ + getFrameMetrics: ( + index: number, + props: FrameMetricProps, + ) => ?{ length: number, offset: number, ... @@ -193,17 +202,18 @@ class ViewabilityHelper { ... }, ): void { + const itemCount = props.getItemCount(props.data); if ( (this._config.waitForInteraction && !this._hasInteracted) || itemCount === 0 || - !getFrameMetrics(0) + !getFrameMetrics(0, props) ) { return; } let viewableIndices = []; if (itemCount) { viewableIndices = this.computeViewableItems( - itemCount, + props, scrollOffset, viewportHeight, getFrameMetrics, diff --git a/Libraries/Lists/VirtualizeUtils.js b/Libraries/Lists/VirtualizeUtils.js index 9351505dcad..3936bf6f649 100644 --- a/Libraries/Lists/VirtualizeUtils.js +++ b/Libraries/Lists/VirtualizeUtils.js @@ -19,14 +19,18 @@ import type {FrameMetricProps} from './VirtualizedListProps'; */ export function elementsThatOverlapOffsets( offsets: Array, - itemCount: number, - getFrameMetrics: (index: number) => { + props: FrameMetricProps, + getFrameMetrics: ( + index: number, + props: FrameMetricProps, + ) => { length: number, offset: number, ... }, zoomScale: number = 1, ): Array { + const itemCount = props.getItemCount(props.data); const result = []; for (let offsetIndex = 0; offsetIndex < offsets.length; offsetIndex++) { const currentOffset = offsets[offsetIndex]; @@ -36,7 +40,7 @@ export function elementsThatOverlapOffsets( while (left <= right) { // eslint-disable-next-line no-bitwise const mid = left + ((right - left) >>> 1); - const frame = getFrameMetrics(mid); + const frame = getFrameMetrics(mid, props); const scaledOffsetStart = frame.offset * zoomScale; const scaledOffsetEnd = (frame.offset + frame.length) * zoomScale; @@ -102,7 +106,10 @@ export function computeWindowedRenderLimits( first: number, last: number, }, - getFrameMetricsApprox: (index: number) => { + getFrameMetricsApprox: ( + index: number, + props: FrameMetricProps, + ) => { length: number, offset: number, ... @@ -145,7 +152,7 @@ export function computeWindowedRenderLimits( const overscanEnd = Math.max(0, visibleEnd + leadFactor * overscanLength); const lastItemOffset = - getFrameMetricsApprox(itemCount - 1).offset * zoomScale; + getFrameMetricsApprox(itemCount - 1, props).offset * zoomScale; if (lastItemOffset < overscanBegin) { // Entire list is before our overscan window return { @@ -157,7 +164,7 @@ export function computeWindowedRenderLimits( // Find the indices that correspond to the items at the render boundaries we're targeting. let [overscanFirst, first, last, overscanLast] = elementsThatOverlapOffsets( [overscanBegin, visibleBegin, visibleEnd, overscanEnd], - itemCount, + props, getFrameMetricsApprox, zoomScale, ); diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index a0dc214d798..7755718a379 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -14,6 +14,7 @@ import type {LayoutEvent, ScrollEvent} from '../Types/CoreEventTypes'; import type {ViewToken} from './ViewabilityHelper'; import type { + FrameMetricProps, Item, Props, RenderItemProps, @@ -1619,7 +1620,10 @@ class VirtualizedList extends React.PureComponent { return {index, item, key: this._keyExtractor(item, index), isViewable}; }; - __getFrameMetricsApprox: (index: number) => { + __getFrameMetricsApprox: ( + index: number, + props?: FrameMetricProps, + ) => { length: number, offset: number, ... @@ -1643,6 +1647,7 @@ class VirtualizedList extends React.PureComponent { _getFrameMetrics = ( index: number, + props?: FrameMetricProps, ): ?{ length: number, offset: number, @@ -1669,11 +1674,9 @@ class VirtualizedList extends React.PureComponent { }; _updateViewableItems(data: any) { - const {getItemCount} = this.props; - this._viewabilityTuples.forEach(tuple => { tuple.viewabilityHelper.onUpdate( - getItemCount(data), + this.props, this._scrollMetrics.offset, this._scrollMetrics.visibleLength, this._getFrameMetrics, diff --git a/Libraries/Lists/VirtualizedList_EXPERIMENTAL.js b/Libraries/Lists/VirtualizedList_EXPERIMENTAL.js index 89d972ef55c..7eeeea55c4a 100644 --- a/Libraries/Lists/VirtualizedList_EXPERIMENTAL.js +++ b/Libraries/Lists/VirtualizedList_EXPERIMENTAL.js @@ -159,7 +159,7 @@ class VirtualizedList extends React.PureComponent { scrollToEnd(params?: ?{animated?: ?boolean, ...}) { const animated = params ? params.animated : true; const veryLast = this.props.getItemCount(this.props.data) - 1; - const frame = this.__getFrameMetricsApprox(veryLast); + const frame = this.__getFrameMetricsApprox(veryLast, this.props); const offset = Math.max( 0, frame.offset + @@ -233,7 +233,7 @@ class VirtualizedList extends React.PureComponent { }); return; } - const frame = this.__getFrameMetricsApprox(index); + const frame = this.__getFrameMetricsApprox(index, this.props); const offset = Math.max( 0, @@ -713,7 +713,6 @@ class VirtualizedList extends React.PureComponent { }, }); } - this._updateViewableItems(null, this.state.cellsAroundViewport); this._updateCellsToRenderBatcher.dispose({abort: true}); this._viewabilityTuples.forEach(tuple => { tuple.viewabilityHelper.dispose(); @@ -960,8 +959,11 @@ class VirtualizedList extends React.PureComponent { ) : section.last; - const firstMetrics = this.__getFrameMetricsApprox(section.first); - const lastMetrics = this.__getFrameMetricsApprox(last); + const firstMetrics = this.__getFrameMetricsApprox( + section.first, + this.props, + ); + const lastMetrics = this.__getFrameMetricsApprox(last, this.props); const spacerSize = lastMetrics.offset + lastMetrics.length - firstMetrics.offset; cells.push( @@ -1273,7 +1275,7 @@ class VirtualizedList extends React.PureComponent { const renderMask = VirtualizedList._createRenderMask( this.props, this.state.cellsAroundViewport, - this._getNonViewportRenderRegions(), + this._getNonViewportRenderRegions(this.props), ); if (!renderMask.equals(this.state.renderMask)) { @@ -1397,7 +1399,7 @@ class VirtualizedList extends React.PureComponent { const framesInLayout = []; const itemCount = this.props.getItemCount(this.props.data); for (let ii = 0; ii < itemCount; ii++) { - const frame = this.__getFrameMetricsApprox(ii); + const frame = this.__getFrameMetricsApprox(ii, this.props); /* $FlowFixMe[prop-missing] (>=0.68.0 site=react_native_fb) This comment * suppresses an error found when Flow v0.68 was deployed. To see the * error delete this comment and run Flow. */ @@ -1407,9 +1409,11 @@ class VirtualizedList extends React.PureComponent { } const windowTop = this.__getFrameMetricsApprox( this.state.cellsAroundViewport.first, + this.props, ).offset; const frameLast = this.__getFrameMetricsApprox( this.state.cellsAroundViewport.last, + this.props, ); const windowLen = frameLast.offset + frameLast.length - windowTop; const visTop = this._scrollMetrics.offset; @@ -1637,7 +1641,8 @@ class VirtualizedList extends React.PureComponent { // Mark as high priority if we're close to the start of the first item // But only if there are items before the first rendered item if (first > 0) { - const distTop = offset - this.__getFrameMetricsApprox(first).offset; + const distTop = + offset - this.__getFrameMetricsApprox(first, this.props).offset; hiPri = hiPri || distTop < 0 || (velocity < -2 && distTop < scrollingThreshold); } @@ -1645,7 +1650,8 @@ class VirtualizedList extends React.PureComponent { // But only if there are items after the last rendered item if (last >= 0 && last < itemCount - 1) { const distBottom = - this.__getFrameMetricsApprox(last).offset - (offset + visibleLength); + this.__getFrameMetricsApprox(last, this.props).offset - + (offset + visibleLength); hiPri = hiPri || distBottom < 0 || @@ -1722,7 +1728,7 @@ class VirtualizedList extends React.PureComponent { const renderMask = VirtualizedList._createRenderMask( props, cellsAroundViewport, - this._getNonViewportRenderRegions(), + this._getNonViewportRenderRegions(props), ); if ( @@ -1743,17 +1749,20 @@ class VirtualizedList extends React.PureComponent { return {index, item, key: this._keyExtractor(item, index), isViewable}; }; - __getFrameMetricsApprox: (index: number) => { + __getFrameMetricsApprox: ( + index: number, + props: FrameMetricProps, + ) => { length: number, offset: number, ... - } = index => { - const frame = this._getFrameMetrics(index); + } = (index, props) => { + const frame = this._getFrameMetrics(index, props); if (frame && frame.index === index) { // check for invalid frames due to row re-ordering return frame; } else { - const {data, getItemCount, getItemLayout} = this.props; + const {data, getItemCount, getItemLayout} = props; invariant( index >= 0 && index < getItemCount(data), 'Tried to get frame for out of range index ' + index, @@ -1771,6 +1780,7 @@ class VirtualizedList extends React.PureComponent { _getFrameMetrics = ( index: number, + props: FrameMetricProps, ): ?{ length: number, offset: number, @@ -1778,7 +1788,7 @@ class VirtualizedList extends React.PureComponent { inLayout?: boolean, ... } => { - const {data, getItem, getItemCount, getItemLayout} = this.props; + const {data, getItem, getItemCount, getItemLayout} = props; invariant( index >= 0 && index < getItemCount(data), 'Tried to get frame for out of range index ' + index, @@ -1796,7 +1806,9 @@ class VirtualizedList extends React.PureComponent { return frame; }; - _getNonViewportRenderRegions = (): $ReadOnlyArray<{ + _getNonViewportRenderRegions = ( + props: FrameMetricProps, + ): $ReadOnlyArray<{ first: number, last: number, }> => { @@ -1811,7 +1823,7 @@ class VirtualizedList extends React.PureComponent { const lastFocusedCellRenderer = this._cellRefs[this._lastFocusedCellKey]; const focusedCellIndex = lastFocusedCellRenderer.props.index; - const itemCount = this.props.getItemCount(this.props.data); + const itemCount = props.getItemCount(props.data); // The cell may have been unmounted and have a stale index if ( @@ -1829,7 +1841,10 @@ class VirtualizedList extends React.PureComponent { i-- ) { first--; - heightOfCellsBeforeFocused += this.__getFrameMetricsApprox(i).length; + heightOfCellsBeforeFocused += this.__getFrameMetricsApprox( + i, + props, + ).length; } let last = focusedCellIndex; @@ -1841,21 +1856,22 @@ class VirtualizedList extends React.PureComponent { i++ ) { last++; - heightOfCellsAfterFocused += this.__getFrameMetricsApprox(i).length; + heightOfCellsAfterFocused += this.__getFrameMetricsApprox( + i, + props, + ).length; } return [{first, last}]; }; _updateViewableItems( - props: ?FrameMetricProps, + props: FrameMetricProps, cellsAroundViewport: {first: number, last: number}, ) { - const itemCount = props ? props.getItemCount(props.data) : 0; - this._viewabilityTuples.forEach(tuple => { tuple.viewabilityHelper.onUpdate( - itemCount, + props, this._scrollMetrics.offset, this._scrollMetrics.visibleLength, this._getFrameMetrics, diff --git a/Libraries/Lists/VirtualizedSectionList.js b/Libraries/Lists/VirtualizedSectionList.js index f17d6e992a5..aa18f60f05c 100644 --- a/Libraries/Lists/VirtualizedSectionList.js +++ b/Libraries/Lists/VirtualizedSectionList.js @@ -140,6 +140,7 @@ class VirtualizedSectionList< if (params.itemIndex > 0 && this.props.stickySectionHeadersEnabled) { const frame = this._listRef.__getFrameMetricsApprox( index - params.itemIndex, + this._listRef.props, ); viewOffset += frame.length; } diff --git a/Libraries/Lists/__tests__/ViewabilityHelper-test.js b/Libraries/Lists/__tests__/ViewabilityHelper-test.js index 3f0a1cedad5..1d0889e3771 100644 --- a/Libraries/Lists/__tests__/ViewabilityHelper-test.js +++ b/Libraries/Lists/__tests__/ViewabilityHelper-test.js @@ -14,6 +14,10 @@ const ViewabilityHelper = require('../ViewabilityHelper'); let rowFrames; let data; +const props = { + data, + getItemCount: () => data.length, +}; function getFrameMetrics(index: number) { const frame = rowFrames[data[index].key]; return {length: frame.height, offset: frame.y}; @@ -34,9 +38,9 @@ describe('computeViewableItems', function () { d: {y: 150, height: 50}, }; data = [{key: 'a'}, {key: 'b'}, {key: 'c'}, {key: 'd'}]; - expect( - helper.computeViewableItems(data.length, 0, 200, getFrameMetrics), - ).toEqual([0, 1, 2, 3]); + expect(helper.computeViewableItems(props, 0, 200, getFrameMetrics)).toEqual( + [0, 1, 2, 3], + ); }); it('returns top 2 rows as viewable (1. entirely visible and 2. majority)', function () { @@ -50,9 +54,9 @@ describe('computeViewableItems', function () { d: {y: 250, height: 50}, }; data = [{key: 'a'}, {key: 'b'}, {key: 'c'}, {key: 'd'}]; - expect( - helper.computeViewableItems(data.length, 0, 200, getFrameMetrics), - ).toEqual([0, 1]); + expect(helper.computeViewableItems(props, 0, 200, getFrameMetrics)).toEqual( + [0, 1], + ); }); it('returns only 2nd row as viewable (majority)', function () { @@ -67,7 +71,7 @@ describe('computeViewableItems', function () { }; data = [{key: 'a'}, {key: 'b'}, {key: 'c'}, {key: 'd'}]; expect( - helper.computeViewableItems(data.length, 25, 200, getFrameMetrics), + helper.computeViewableItems(props, 25, 200, getFrameMetrics), ).toEqual([1]); }); @@ -77,9 +81,9 @@ describe('computeViewableItems', function () { }); rowFrames = {}; data = []; - expect( - helper.computeViewableItems(data.length, 0, 200, getFrameMetrics), - ).toEqual([]); + expect(helper.computeViewableItems(props, 0, 200, getFrameMetrics)).toEqual( + [], + ); }); it('handles different view area coverage percent thresholds', function () { @@ -92,39 +96,39 @@ describe('computeViewableItems', function () { data = [{key: 'a'}, {key: 'b'}, {key: 'c'}, {key: 'd'}]; let helper = new ViewabilityHelper({viewAreaCoveragePercentThreshold: 0}); + expect(helper.computeViewableItems(props, 0, 50, getFrameMetrics)).toEqual([ + 0, + ]); + expect(helper.computeViewableItems(props, 1, 50, getFrameMetrics)).toEqual([ + 0, 1, + ]); expect( - helper.computeViewableItems(data.length, 0, 50, getFrameMetrics), - ).toEqual([0]); - expect( - helper.computeViewableItems(data.length, 1, 50, getFrameMetrics), - ).toEqual([0, 1]); - expect( - helper.computeViewableItems(data.length, 199, 50, getFrameMetrics), + helper.computeViewableItems(props, 199, 50, getFrameMetrics), ).toEqual([1, 2]); expect( - helper.computeViewableItems(data.length, 250, 50, getFrameMetrics), + helper.computeViewableItems(props, 250, 50, getFrameMetrics), ).toEqual([2]); helper = new ViewabilityHelper({viewAreaCoveragePercentThreshold: 100}); + expect(helper.computeViewableItems(props, 0, 200, getFrameMetrics)).toEqual( + [0, 1], + ); + expect(helper.computeViewableItems(props, 1, 200, getFrameMetrics)).toEqual( + [1], + ); expect( - helper.computeViewableItems(data.length, 0, 200, getFrameMetrics), - ).toEqual([0, 1]); - expect( - helper.computeViewableItems(data.length, 1, 200, getFrameMetrics), - ).toEqual([1]); - expect( - helper.computeViewableItems(data.length, 400, 200, getFrameMetrics), + helper.computeViewableItems(props, 400, 200, getFrameMetrics), ).toEqual([2]); expect( - helper.computeViewableItems(data.length, 600, 200, getFrameMetrics), + helper.computeViewableItems(props, 600, 200, getFrameMetrics), ).toEqual([3]); helper = new ViewabilityHelper({viewAreaCoveragePercentThreshold: 10}); expect( - helper.computeViewableItems(data.length, 30, 200, getFrameMetrics), + helper.computeViewableItems(props, 30, 200, getFrameMetrics), ).toEqual([0, 1, 2]); expect( - helper.computeViewableItems(data.length, 31, 200, getFrameMetrics), + helper.computeViewableItems(props, 31, 200, getFrameMetrics), ).toEqual([1, 2]); }); @@ -137,30 +141,30 @@ describe('computeViewableItems', function () { }; data = [{key: 'a'}, {key: 'b'}, {key: 'c'}, {key: 'd'}]; let helper = new ViewabilityHelper({itemVisiblePercentThreshold: 0}); - expect( - helper.computeViewableItems(data.length, 0, 50, getFrameMetrics), - ).toEqual([0]); - expect( - helper.computeViewableItems(data.length, 1, 50, getFrameMetrics), - ).toEqual([0, 1]); + expect(helper.computeViewableItems(props, 0, 50, getFrameMetrics)).toEqual([ + 0, + ]); + expect(helper.computeViewableItems(props, 1, 50, getFrameMetrics)).toEqual([ + 0, 1, + ]); helper = new ViewabilityHelper({itemVisiblePercentThreshold: 100}); - expect( - helper.computeViewableItems(data.length, 0, 250, getFrameMetrics), - ).toEqual([0, 1, 2]); - expect( - helper.computeViewableItems(data.length, 1, 250, getFrameMetrics), - ).toEqual([1, 2]); + expect(helper.computeViewableItems(props, 0, 250, getFrameMetrics)).toEqual( + [0, 1, 2], + ); + expect(helper.computeViewableItems(props, 1, 250, getFrameMetrics)).toEqual( + [1, 2], + ); helper = new ViewabilityHelper({itemVisiblePercentThreshold: 10}); expect( - helper.computeViewableItems(data.length, 184, 20, getFrameMetrics), + helper.computeViewableItems(props, 184, 20, getFrameMetrics), ).toEqual([1]); expect( - helper.computeViewableItems(data.length, 185, 20, getFrameMetrics), + helper.computeViewableItems(props, 185, 20, getFrameMetrics), ).toEqual([1, 2]); expect( - helper.computeViewableItems(data.length, 186, 20, getFrameMetrics), + helper.computeViewableItems(props, 186, 20, getFrameMetrics), ).toEqual([2]); }); }); @@ -174,7 +178,7 @@ describe('onUpdate', function () { data = [{key: 'a'}]; const onViewableItemsChanged = jest.fn(); helper.onUpdate( - data.length, + props, 0, 200, getFrameMetrics, @@ -188,7 +192,7 @@ describe('onUpdate', function () { viewableItems: [{isViewable: true, key: 'a'}], }); helper.onUpdate( - data.length, + props, 0, 200, getFrameMetrics, @@ -197,7 +201,7 @@ describe('onUpdate', function () { ); expect(onViewableItemsChanged.mock.calls.length).toBe(1); // nothing changed! helper.onUpdate( - data.length, + props, 100, 200, getFrameMetrics, @@ -221,7 +225,7 @@ describe('onUpdate', function () { data = [{key: 'a'}, {key: 'b'}]; const onViewableItemsChanged = jest.fn(); helper.onUpdate( - data.length, + props, 0, 200, getFrameMetrics, @@ -235,7 +239,7 @@ describe('onUpdate', function () { viewableItems: [{isViewable: true, key: 'a'}], }); helper.onUpdate( - data.length, + props, 100, 200, getFrameMetrics, @@ -253,7 +257,7 @@ describe('onUpdate', function () { ], }); helper.onUpdate( - data.length, + props, 200, 200, getFrameMetrics, @@ -280,7 +284,7 @@ describe('onUpdate', function () { data = [{key: 'a'}, {key: 'b'}]; const onViewableItemsChanged = jest.fn(); helper.onUpdate( - data.length, + props, 0, 200, getFrameMetrics, @@ -314,7 +318,7 @@ describe('onUpdate', function () { data = [{key: 'a'}, {key: 'b'}]; const onViewableItemsChanged = jest.fn(); helper.onUpdate( - data.length, + props, 0, 200, getFrameMetrics, @@ -322,7 +326,7 @@ describe('onUpdate', function () { onViewableItemsChanged, ); helper.onUpdate( - data.length, + props, 300, // scroll past item 'a' 200, getFrameMetrics, @@ -355,7 +359,7 @@ describe('onUpdate', function () { data = [{key: 'a'}, {key: 'b'}]; const onViewableItemsChanged = jest.fn(); helper.onUpdate( - data.length, + props, 0, 100, getFrameMetrics, @@ -367,7 +371,7 @@ describe('onUpdate', function () { helper.recordInteraction(); helper.onUpdate( - data.length, + props, 20, 100, getFrameMetrics, @@ -394,7 +398,7 @@ describe('onUpdate', function () { data = [{key: 'a'}, {key: 'b'}]; const onViewableItemsChanged = jest.fn(); helper.onUpdate( - data.length, + props, 0, 200, getFrameMetrics, @@ -419,7 +423,7 @@ describe('onUpdate', function () { helper.resetViewableIndices(); helper.onUpdate( - data.length, + props, 0, 200, getFrameMetrics, diff --git a/Libraries/Lists/__tests__/VirtualizeUtils-test.js b/Libraries/Lists/__tests__/VirtualizeUtils-test.js index 5f4de3e52e1..f2ac3fd821d 100644 --- a/Libraries/Lists/__tests__/VirtualizeUtils-test.js +++ b/Libraries/Lists/__tests__/VirtualizeUtils-test.js @@ -49,7 +49,7 @@ describe('elementsThatOverlapOffsets', function () { }; } expect( - elementsThatOverlapOffsets(offsets, 100, getFrameMetrics, 1), + elementsThatOverlapOffsets(offsets, fakeProps(100), getFrameMetrics, 1), ).toEqual([0, 2, 3, 4]); }); it('handles variable length', function () { @@ -62,7 +62,12 @@ describe('elementsThatOverlapOffsets', function () { {offset: 950, length: 150}, ]; expect( - elementsThatOverlapOffsets(offsets, frames.length, ii => frames[ii], 1), + elementsThatOverlapOffsets( + offsets, + fakeProps(frames.length), + ii => frames[ii], + 1, + ), ).toEqual([1, 1, 3]); }); it('handles frame boundaries', function () { @@ -74,7 +79,7 @@ describe('elementsThatOverlapOffsets', function () { }; } expect( - elementsThatOverlapOffsets(offsets, 100, getFrameMetrics, 1), + elementsThatOverlapOffsets(offsets, fakeProps(100), getFrameMetrics, 1), ).toEqual([0, 0, 1, 2]); }); it('handles out of bounds', function () { @@ -85,7 +90,19 @@ describe('elementsThatOverlapOffsets', function () { {offset: 250, length: 100}, ]; expect( - elementsThatOverlapOffsets(offsets, frames.length, ii => frames[ii], 1), + elementsThatOverlapOffsets( + offsets, + fakeProps(frames.length), + ii => frames[ii], + 1, + ), ).toEqual([undefined, 1]); }); }); + +function fakeProps(length) { + return { + data: new Array(length).fill({}), + getItemCount: () => length, + }; +}