@@ -50,6 +50,7 @@ import {
5050 keyExtractor as defaultKeyExtractor ,
5151} from './VirtualizeUtils' ;
5252import invariant from 'invariant' ;
53+ import nullthrows from 'nullthrows' ;
5354import * as React from 'react' ;
5455
5556export type { RenderItemProps , RenderItemType , Separators } ;
@@ -420,21 +421,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
420421
421422 constructor ( props : Props ) {
422423 super ( props ) ;
423- invariant (
424- // $FlowFixMe[prop-missing]
425- ! props . onScroll || ! props . onScroll . __isNative ,
426- 'Components based on VirtualizedList must be wrapped with Animated.createAnimatedComponent ' +
427- 'to support native onScroll events with useNativeDriver' ,
428- ) ;
429- invariant (
430- windowSizeOrDefault ( props . windowSize ) > 0 ,
431- 'VirtualizedList: The windowSize prop must be present and set to a value greater than 0.' ,
432- ) ;
433-
434- invariant (
435- props . getItemCount ,
436- 'VirtualizedList: The "getItemCount" prop must be provided' ,
437- ) ;
424+ this . checkProps ( props ) ;
438425
439426 this . _fillRateHelper = new FillRateHelper ( this . _getFrameMetrics ) ;
440427 this . _updateCellsToRenderBatcher = new Batchinator (
@@ -459,11 +446,6 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
459446 }
460447 }
461448
462- invariant (
463- ! this . context ,
464- 'Unexpectedly saw VirtualizedListContext available in ctor' ,
465- ) ;
466-
467449 const initialRenderRegion = VirtualizedList . _initialRenderRegion ( props ) ;
468450
469451 this . state = {
@@ -472,6 +454,53 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
472454 } ;
473455 }
474456
457+ checkProps ( props : Props ) {
458+ const { onScroll, windowSize, getItemCount, data, initialScrollIndex} =
459+ props ;
460+
461+ invariant (
462+ // $FlowFixMe[prop-missing]
463+ ! onScroll || ! onScroll . __isNative ,
464+ 'Components based on VirtualizedList must be wrapped with Animated.createAnimatedComponent ' +
465+ 'to support native onScroll events with useNativeDriver' ,
466+ ) ;
467+ invariant (
468+ windowSizeOrDefault ( windowSize ) > 0 ,
469+ 'VirtualizedList: The windowSize prop must be present and set to a value greater than 0.' ,
470+ ) ;
471+
472+ invariant (
473+ getItemCount ,
474+ 'VirtualizedList: The "getItemCount" prop must be provided' ,
475+ ) ;
476+
477+ const itemCount = getItemCount ( data ) ;
478+
479+ if (
480+ initialScrollIndex != null &&
481+ ( initialScrollIndex < 0 ||
482+ ( itemCount > 0 && initialScrollIndex >= itemCount ) ) &&
483+ ! this . _hasWarned . initialScrollIndex
484+ ) {
485+ console . warn (
486+ `initialScrollIndex "${ initialScrollIndex } " is not valid (list has ${ itemCount } items)` ,
487+ ) ;
488+ this . _hasWarned . initialScrollIndex = true ;
489+ }
490+
491+ if ( __DEV__ && ! this . _hasWarned . flexWrap ) {
492+ // $FlowFixMe[underconstrained-implicit-instantiation]
493+ const flatStyles = StyleSheet . flatten ( this . props . contentContainerStyle ) ;
494+ if ( flatStyles != null && flatStyles . flexWrap === 'wrap' ) {
495+ console . warn (
496+ '`flexWrap: `wrap`` is not supported with the `VirtualizedList` components.' +
497+ 'Consider using `numColumns` with `FlatList` instead.' ,
498+ ) ;
499+ this . _hasWarned . flexWrap = true ;
500+ }
501+ }
502+ }
503+
475504 static _createRenderMask (
476505 props : Props ,
477506 cellsAroundViewport : { first : number , last : number } ,
@@ -518,15 +547,21 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
518547
519548 static _initialRenderRegion ( props : Props ) : { first : number , last : number } {
520549 const itemCount = props . getItemCount ( props . data ) ;
521- const scrollIndex = Math . floor ( Math . max ( 0 , props . initialScrollIndex ?? 0 ) ) ;
550+
551+ const firstCellIndex = Math . max (
552+ 0 ,
553+ Math . min ( itemCount - 1 , Math . floor ( props . initialScrollIndex ?? 0 ) ) ,
554+ ) ;
555+
556+ const lastCellIndex =
557+ Math . min (
558+ itemCount ,
559+ firstCellIndex + initialNumToRenderOrDefault ( props . initialNumToRender ) ,
560+ ) - 1 ;
522561
523562 return {
524- first : scrollIndex ,
525- last :
526- Math . min (
527- itemCount ,
528- scrollIndex + initialNumToRenderOrDefault ( props . initialNumToRender ) ,
529- ) - 1 ,
563+ first : firstCellIndex ,
564+ last : lastCellIndex ,
530565 } ;
531566 }
532567
@@ -807,16 +842,7 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
807842 }
808843
809844 render ( ) : React . Node {
810- if ( __DEV__ ) {
811- // $FlowFixMe[underconstrained-implicit-instantiation]
812- const flatStyles = StyleSheet . flatten ( this . props . contentContainerStyle ) ;
813- if ( flatStyles != null && flatStyles . flexWrap === 'wrap' ) {
814- console . warn (
815- '`flexWrap: `wrap`` is not supported with the `VirtualizedList` components.' +
816- 'Consider using `numColumns` with `FlatList` instead.' ,
817- ) ;
818- }
819- }
845+ this . checkProps ( this . props ) ;
820846 const { ListEmptyComponent, ListFooterComponent, ListHeaderComponent} =
821847 this . props ;
822848 const { data, horizontal} = this . props ;
@@ -1507,10 +1533,17 @@ class VirtualizedList extends StateSafePureComponent<Props, State> {
15071533 ! this . _hasTriggeredInitialScrollToIndex
15081534 ) {
15091535 if ( this . props . contentOffset == null ) {
1510- this . scrollToIndex ( {
1511- animated : false ,
1512- index : this . props . initialScrollIndex ,
1513- } ) ;
1536+ if (
1537+ this . props . initialScrollIndex <
1538+ this . props . getItemCount ( this . props . data )
1539+ ) {
1540+ this . scrollToIndex ( {
1541+ animated : false ,
1542+ index : nullthrows ( this . props . initialScrollIndex ) ,
1543+ } ) ;
1544+ } else {
1545+ this . scrollToEnd ( { animated : false } ) ;
1546+ }
15141547 }
15151548 this . _hasTriggeredInitialScrollToIndex = true ;
15161549 }
0 commit comments