From fae2125db0d89d9a03fb5901015498615f178640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Billioud?= Date: Mon, 25 Feb 2019 13:17:03 +0100 Subject: [PATCH 1/4] Improve inverted VirtualizedList implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use flex instead of complex transform inversion. Better for performance, readability and provides natural behaviour for onEndReached. Signed-off-by: François Billioud --- Libraries/Lists/VirtualizedList.js | 55 ++++++++++++------------------ 1 file changed, 21 insertions(+), 34 deletions(-) diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index a97cb7128440..d699a5749f85 100644 --- a/Libraries/Lists/VirtualizedList.js +++ b/Libraries/Lists/VirtualizedList.js @@ -653,7 +653,6 @@ class VirtualizedList extends React.PureComponent { stickyIndicesFromProps: Set, first: number, last: number, - inversionStyle: ViewStyleProp, ) { const { CellRendererComponent, @@ -683,7 +682,6 @@ class VirtualizedList extends React.PureComponent { fillRateHelper={this._fillRateHelper} horizontal={horizontal} index={ii} - inversionStyle={inversionStyle} item={item} key={key} prevCellKey={prevCellKey} @@ -758,10 +756,7 @@ class VirtualizedList extends React.PureComponent { key="$header"> + style={this.props.ListHeaderComponentStyle}> { // $FlowFixMe - Typing ReactNativeComponent revealed errors element @@ -785,7 +780,6 @@ class VirtualizedList extends React.PureComponent { stickyIndicesFromProps, 0, lastInitialIndex, - inversionStyle, ); const firstAfterInitial = Math.max(lastInitialIndex + 1, first); if (!isVirtualizationDisabled && first > lastInitialIndex + 1) { @@ -810,7 +804,6 @@ class VirtualizedList extends React.PureComponent { stickyIndicesFromProps, ii, ii, - inversionStyle, ); const trailSpace = this._getFrameMetricsApprox(first).offset - @@ -839,7 +832,6 @@ class VirtualizedList extends React.PureComponent { stickyIndicesFromProps, firstAfterInitial, last, - inversionStyle, ); if (!this._hasWarned.keys && _usedIndexForKey) { console.warn( @@ -884,7 +876,7 @@ class VirtualizedList extends React.PureComponent { element.props.onLayout(event); } }, - style: [element.props.style, inversionStyle], + style: element.props.style, }), ); } @@ -901,10 +893,7 @@ class VirtualizedList extends React.PureComponent { key="$footer"> + style={this.props.ListFooterComponentStyle}> { // $FlowFixMe - Typing ReactNativeComponent revealed errors element @@ -921,6 +910,7 @@ class VirtualizedList extends React.PureComponent { onScrollBeginDrag: this._onScrollBeginDrag, onScrollEndDrag: this._onScrollEndDrag, onMomentumScrollEnd: this._onMomentumScrollEnd, + contentContainerStyle: inversionStyle, scrollEventThrottle: this.props.scrollEventThrottle, // TODO: Android support invertStickyHeaders: this.props.invertStickyHeaders !== undefined @@ -928,12 +918,6 @@ class VirtualizedList extends React.PureComponent { : this.props.inverted, stickyHeaderIndices, }; - if (inversionStyle && itemCount !== 0) { - /* $FlowFixMe(>=0.70.0 site=react_native_fb) This comment suppresses an - * error found when Flow v0.70 was deployed. To see the error delete - * this comment and run Flow. */ - scrollProps.style = [inversionStyle, this.props.style]; - } this._hasMore = this.state.last < this.props.getItemCount(this.props.data) - 1; @@ -980,6 +964,7 @@ class VirtualizedList extends React.PureComponent { _fillRateHelper: FillRateHelper; _frames = {}; _footerLength = 0; + _distanceFromEnd = 0; _hasDataChangedSinceEndReached = true; _hasInteracted = false; _hasMore = false; @@ -1243,9 +1228,12 @@ class VirtualizedList extends React.PureComponent { getItemCount, onEndReached, onEndReachedThreshold, + inverted, } = this.props; const {contentLength, visibleLength, offset} = this._scrollMetrics; - const distanceFromEnd = contentLength - visibleLength - offset; + const distanceFromEnd = inverted + ? offset + : contentLength - visibleLength - offset; if ( onEndReached && this.state.last === getItemCount(data) - 1 && @@ -1253,12 +1241,15 @@ class VirtualizedList extends React.PureComponent { * error found when Flow v0.63 was deployed. To see the error delete this * comment and run Flow. */ distanceFromEnd < onEndReachedThreshold * visibleLength && + distanceFromEnd !== this._distanceFromEnd && (this._hasDataChangedSinceEndReached || this._scrollMetrics.contentLength !== this._sentEndForContentLength) ) { // Only call onEndReached once for a given dataset + content length. this._hasDataChangedSinceEndReached = false; this._sentEndForContentLength = this._scrollMetrics.contentLength; + //We record the value to prevent from calling twice, especially when distanceFromEnd===0 as the scroll will stick to the top + this._distanceFromEnd = distanceFromEnd; onEndReached({distanceFromEnd}); } } @@ -1447,7 +1438,7 @@ class VirtualizedList extends React.PureComponent { }; _updateCellsToRender = () => { - const {data, getItemCount, onEndReachedThreshold} = this.props; + const {data, getItemCount, onEndReachedThreshold, inverted} = this.props; const isVirtualizationDisabled = this._isVirtualizationDisabled(); this._updateViewableItems(data); if (!data) { @@ -1476,7 +1467,9 @@ class VirtualizedList extends React.PureComponent { } } else { const {contentLength, offset, visibleLength} = this._scrollMetrics; - const distanceFromEnd = contentLength - visibleLength - offset; + const distanceFromEnd = inverted + ? offset + : contentLength - visibleLength - offset; const renderAhead = /* $FlowFixMe(>=0.63.0 site=react_native_fb) This comment suppresses * an error found when Flow v0.63 was deployed. To see the error @@ -1619,7 +1612,6 @@ class CellRenderer extends React.Component< fillRateHelper: FillRateHelper, horizontal: ?boolean, index: number, - inversionStyle: ViewStyleProp, item: Item, onLayout: (event: Object) => void, // This is extracted by ScrollViewStickyHeader onUnmount: (cellKey: string) => void, @@ -1695,7 +1687,6 @@ class CellRenderer extends React.Component< horizontal, item, index, - inversionStyle, parentProps, } = this.props; const {renderItem, getItemLayout} = parentProps; @@ -1717,13 +1708,9 @@ class CellRenderer extends React.Component< const itemSeparator = ItemSeparatorComponent && ( ); - const cellStyle = inversionStyle - ? horizontal - ? [{flexDirection: 'row-reverse'}, inversionStyle] - : [{flexDirection: 'column-reverse'}, inversionStyle] - : horizontal - ? [{flexDirection: 'row'}, inversionStyle] - : inversionStyle; + const cellStyle = horizontal + ? {flexDirection: 'row'} + : {flexDirection: 'column'}; if (!CellRendererComponent) { return ( /* $FlowFixMe(>=0.89.0 site=react_native_fb) This comment suppresses an @@ -1772,10 +1759,10 @@ class VirtualizedCellWrapper extends React.Component<{ const styles = StyleSheet.create({ verticallyInverted: { - transform: [{scaleY: -1}], + flexDirection: 'row-reverse', }, horizontallyInverted: { - transform: [{scaleX: -1}], + flexDirection: 'column-reverse', }, debug: { flex: 1, From f0d1570a17f429414b2d7b79ffb144a5cf2fc8f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Billioud?= Date: Mon, 25 Feb 2019 14:26:36 +0100 Subject: [PATCH 2/4] Update snapshots MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: François Billioud --- .../__snapshots__/FlatList-test.js.snap | 40 ++- .../__snapshots__/SectionList-test.js.snap | 125 +++++++-- .../VirtualizedList-test.js.snap | 248 +++++++++--------- 3 files changed, 267 insertions(+), 146 deletions(-) diff --git a/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap b/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap index 5b2c34d48d48..b49786b6e7dd 100644 --- a/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap +++ b/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap @@ -6,6 +6,7 @@ exports[`FlatList renders all the bells and whistles 1`] = ` ListEmptyComponent={[Function]} ListFooterComponent={[Function]} ListHeaderComponent={[Function]} + contentContainerStyle={null} data={ Array [ Object { @@ -65,7 +66,11 @@ exports[`FlatList renders all the bells and whistles 1`] = `
@@ -89,6 +106,7 @@ exports[`SectionList rendering empty section headers is fine 1`] = ` exports[`SectionList renders a footer when there is no data 1`] = ` @@ -475,32 +520,14 @@ exports[`VirtualizedList renders all the bells and whistles 1`] = `