From c40a938ead3662aedc823e70f12f68e98985c8b7 Mon Sep 17 00:00:00 2001 From: Spencer Ahrens Date: Tue, 23 Apr 2019 16:00:44 -0700 Subject: [PATCH] Fix infinite `setState` in `VirtualizedList` Reviewed By: larrylin28 Differential Revision: D14990686 fbshipit-source-id: 632fa0e4e11feff9dcfb4ac62ba8bc7a6c0393a5 --- Libraries/Lists/VirtualizedList.js | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 72686db4e322c1..67abdc1765877c 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -982,7 +982,19 @@ class VirtualizedList extends React.PureComponent { tuple.viewabilityHelper.resetViewableIndices(); }); } + // The `this._hiPriInProgress` is guaranteeing a hiPri cell update will only happen + // once per fiber update. The `_scheduleCellsToRenderUpdate` will set it to true + // if a hiPri update needs to perform. If `componentDidUpdate` is triggered with + // `this._hiPriInProgress=true`, means it's triggered by the hiPri update. The + // `_scheduleCellsToRenderUpdate` will check this condition and not perform + // another hiPri update. + const hiPriInProgress = this._hiPriInProgress; this._scheduleCellsToRenderUpdate(); + // Make sure setting `this._hiPriInProgress` back to false after `componentDidUpdate` + // is triggered with `this._hiPriInProgress = true` + if (hiPriInProgress) { + this._hiPriInProgress = false; + } } _averageCellLength = 0; @@ -993,13 +1005,14 @@ class VirtualizedList extends React.PureComponent { _frames = {}; _footerLength = 0; _hasDataChangedSinceEndReached = true; + _hasDoneInitialScroll = false; _hasInteracted = false; _hasMore = false; _hasWarned = {}; - _highestMeasuredFrameIndex = 0; _headerLength = 0; + _hiPriInProgress: boolean = false; // flag to prevent infinite hiPri cell limit update + _highestMeasuredFrameIndex = 0; _indicesToKeys: Map = new Map(); - _hasDoneInitialScroll = false; _nestedChildLists: Map< string, {ref: ?VirtualizedList, state: ?ChildListState}, @@ -1422,7 +1435,10 @@ class VirtualizedList extends React.PureComponent { // Otherwise, it would just render as many cells as it can (of zero dimension), // each time through attempting to render more (limited by maxToRenderPerBatch), // starving the renderer from actually laying out the objects and computing _averageCellLength. - if (hiPri && this._averageCellLength) { + // If this is triggered in an `componentDidUpdate` followed by a hiPri cellToRenderUpdate + // We shouldn't do another hipri cellToRenderUpdate + if (hiPri && this._averageCellLength && !this._hiPriInProgress) { + this._hiPriInProgress = true; // Don't worry about interactions when scrolling quickly; focus on filling content as fast // as possible. this._updateCellsToRenderBatcher.dispose({abort: true});