From 1ee602b655e2eb4ea3b054fd9ed6da87ee95f0bd Mon Sep 17 00:00:00 2001 From: Mike Lambert Date: Thu, 22 Jun 2017 18:35:43 -0700 Subject: [PATCH] Fix problems if _updateCellsToRender gets called too early Summary: (prior to the scroll metrics being set up, or prior to the view being scrolled to the right location). I'm using a StackNavigator to push a FlatList secondary screen, and it was causing extraneous rendering (item X ->item 0 -> item X) I've logged inside the render functions of my `renderItem` function, and verified that it no longer attempts to render item 0 anymore. And I've verified from the `VirtualizedList.state` no longer renders a `{first: 0, last: 0}`, but persistently stays at `{first: X, last: X}` from start until things stabilize. Closes https://github.com/facebook/react-native/pull/14562 Reviewed By: bvaughn Differential Revision: D5283771 Pulled By: sahrens fbshipit-source-id: 0f70ac0b89922449bd20bfa69edbc8939eafdf1f --- Libraries/Lists/VirtualizedList.js | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index 21abddc93..0e4556672 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -1026,12 +1026,24 @@ class VirtualizedList extends React.PureComponent { this.setState(state => { let newState; if (!isVirtualizationDisabled) { - newState = computeWindowedRenderLimits( - this.props, - state, - this._getFrameMetricsApprox, - this._scrollMetrics, - ); + // If we run this with bogus data, we'll force-render window {first: 0, last: 0}, + // and wipe out the initialNumToRender rendered elements. + // So let's wait until the scroll view metrics have been set up. And until then, + // we will trust the initialNumToRender suggestion + if (this._scrollMetrics.visibleLength) { + // If we have a non-zero initialScrollIndex and run this before we've scrolled, + // we'll wipe out the initialNumToRender rendered elements starting at initialScrollIndex. + // So let's wait until we've scrolled the view to the right place. And until then, + // we will trust the initialScrollIndex suggestion. + if (!this.props.initialScrollIndex || this._scrollMetrics.offset) { + newState = computeWindowedRenderLimits( + this.props, + state, + this._getFrameMetricsApprox, + this._scrollMetrics, + ); + } + } } else { const {contentLength, offset, visibleLength} = this._scrollMetrics; const distanceFromEnd = contentLength - visibleLength - offset;