Skip to content

Commit ff6a912

Browse files
cipolleschifacebook-github-bot
authored andcommitted
Ignore stale minimum-view-time viewability updates
Summary: Changelog: [General][Fixed] - Ignore stale viewability updates while enforcing minimum view time Minimum view-time callbacks can outlive a newer viewport update. During initial layout, callbacks for intermediate viewport snapshots can fire after the current snapshot and replace the correct visible-item set. Discard callbacks whose captured visible-index set is no longer current, and cover the transition with a unit test. Differential Revision: D115740467
1 parent 3b8886a commit ff6a912

2 files changed

Lines changed: 56 additions & 0 deletions

File tree

‎packages/virtualized-lists/Lists/ViewabilityHelper.js‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,10 @@ class ViewabilityHelper {
231231
* comment suppresses an error found when Flow v0.63 was deployed. To
232232
* see the error delete this comment and run Flow. */
233233
this._timers.delete(handle);
234+
// `onUpdate` replaces the array whenever the visible set changes.
235+
if (this._viewableIndices !== viewableIndices) {
236+
return;
237+
}
234238
this._onUpdateSync(
235239
props,
236240
viewableIndices,

‎packages/virtualized-lists/Lists/__tests__/ViewabilityHelper-test.js‎

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,58 @@ describe('onUpdate', function () {
342342
});
343343
});
344344

345+
it('minimumViewTime ignores stale viewability updates', function () {
346+
const helper = new ViewabilityHelper({
347+
minimumViewTime: 350,
348+
viewAreaCoveragePercentThreshold: 0,
349+
});
350+
rowFrames = {
351+
a: {y: 0, height: 200},
352+
b: {y: 200, height: 200},
353+
};
354+
data = [{key: 'a'}, {key: 'b'}];
355+
const onViewableItemsChanged = jest.fn();
356+
helper.onUpdate(
357+
props,
358+
0,
359+
200,
360+
// $FlowFixMe[incompatible-type] - Invalid `ListMetricsAggregator`.
361+
{getCellMetrics},
362+
createViewToken,
363+
onViewableItemsChanged,
364+
);
365+
helper.onUpdate(
366+
props,
367+
0,
368+
400,
369+
// $FlowFixMe[incompatible-type] - Invalid `ListMetricsAggregator`.
370+
{getCellMetrics},
371+
createViewToken,
372+
onViewableItemsChanged,
373+
);
374+
375+
jest.runAllTimers();
376+
377+
expect(onViewableItemsChanged.mock.calls).toEqual([
378+
[
379+
{
380+
changed: [
381+
{isViewable: true, key: 'a'},
382+
{isViewable: true, key: 'b'},
383+
],
384+
viewabilityConfig: {
385+
minimumViewTime: 350,
386+
viewAreaCoveragePercentThreshold: 0,
387+
},
388+
viewableItems: [
389+
{isViewable: true, key: 'a'},
390+
{isViewable: true, key: 'b'},
391+
],
392+
},
393+
],
394+
]);
395+
});
396+
345397
it('minimumViewTime skips briefly visible items', function () {
346398
const helper = new ViewabilityHelper({
347399
minimumViewTime: 350,

0 commit comments

Comments
 (0)