diff --git a/Libraries/Lists/VirtualizedList.js b/Libraries/Lists/VirtualizedList.js index a97cb7128440..31cb95fbc823 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, @@ -662,6 +661,7 @@ class VirtualizedList extends React.PureComponent { getItem, getItemCount, horizontal, + inverted, keyExtractor, } = this.props; const stickyOffset = this.props.ListHeaderComponent ? 1 : 0; @@ -682,8 +682,8 @@ class VirtualizedList extends React.PureComponent { cellKey={key} fillRateHelper={this._fillRateHelper} horizontal={horizontal} + inverted={inverted} index={ii} - inversionStyle={inversionStyle} item={item} key={key} prevCellKey={prevCellKey} @@ -758,10 +758,7 @@ class VirtualizedList extends React.PureComponent { key="$header"> + style={this.props.ListHeaderComponentStyle}> { // $FlowFixMe - Typing ReactNativeComponent revealed errors element @@ -785,7 +782,6 @@ class VirtualizedList extends React.PureComponent { stickyIndicesFromProps, 0, lastInitialIndex, - inversionStyle, ); const firstAfterInitial = Math.max(lastInitialIndex + 1, first); if (!isVirtualizationDisabled && first > lastInitialIndex + 1) { @@ -810,7 +806,6 @@ class VirtualizedList extends React.PureComponent { stickyIndicesFromProps, ii, ii, - inversionStyle, ); const trailSpace = this._getFrameMetricsApprox(first).offset - @@ -839,7 +834,6 @@ class VirtualizedList extends React.PureComponent { stickyIndicesFromProps, firstAfterInitial, last, - inversionStyle, ); if (!this._hasWarned.keys && _usedIndexForKey) { console.warn( @@ -884,7 +878,7 @@ class VirtualizedList extends React.PureComponent { element.props.onLayout(event); } }, - style: [element.props.style, inversionStyle], + style: element.props.style, }), ); } @@ -901,10 +895,7 @@ class VirtualizedList extends React.PureComponent { key="$footer"> + style={this.props.ListFooterComponentStyle}> { // $FlowFixMe - Typing ReactNativeComponent revealed errors element @@ -921,6 +912,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 +920,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 +966,7 @@ class VirtualizedList extends React.PureComponent { _fillRateHelper: FillRateHelper; _frames = {}; _footerLength = 0; + _distanceFromEnd = 0; _hasDataChangedSinceEndReached = true; _hasInteracted = false; _hasMore = false; @@ -1243,9 +1230,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 +1243,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 +1440,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 +1469,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 @@ -1618,8 +1613,8 @@ class CellRenderer extends React.Component< cellKey: string, fillRateHelper: FillRateHelper, horizontal: ?boolean, + inverted: ?boolean, index: number, - inversionStyle: ViewStyleProp, item: Item, onLayout: (event: Object) => void, // This is extracted by ScrollViewStickyHeader onUnmount: (cellKey: string) => void, @@ -1693,9 +1688,9 @@ class CellRenderer extends React.Component< ItemSeparatorComponent, fillRateHelper, horizontal, + inverted, item, index, - inversionStyle, parentProps, } = this.props; const {renderItem, getItemLayout} = parentProps; @@ -1717,13 +1712,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: inverted ? 'row-reverse' : 'row'} + : {flexDirection: inverted ? 'column-reverse' : 'column'}; if (!CellRendererComponent) { return ( /* $FlowFixMe(>=0.89.0 site=react_native_fb) This comment suppresses an @@ -1772,10 +1763,10 @@ class VirtualizedCellWrapper extends React.Component<{ const styles = StyleSheet.create({ verticallyInverted: { - transform: [{scaleY: -1}], + flexDirection: 'column-reverse', }, horizontallyInverted: { - transform: [{scaleX: -1}], + flexDirection: 'row-reverse', }, debug: { flex: 1, 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`] = `