@@ -62,20 +62,29 @@ if (Platform.OS === 'android') {
62
62
RCTScrollContentView = ScrollContentViewNativeComponent ;
63
63
}
64
64
65
- export type ScrollResponderType = {
66
- // We'd like to do ...ScrollView here, however Flow doesn't seem
67
- // to see the imperative methods of ScrollView that way. Workaround the
68
- // issue by specifying them manually.
65
+ // Public methods for ScrollView
66
+ export type ScrollViewImperativeMethods = $ReadOnly < { |
67
+ getScrollResponder : $PropertyType < ScrollView , 'getScrollResponder' > ,
69
68
getScrollableNode : $PropertyType < ScrollView , 'getScrollableNode' > ,
70
69
getInnerViewNode : $PropertyType < ScrollView , 'getInnerViewNode' > ,
71
70
getInnerViewRef : $PropertyType < ScrollView , 'getInnerViewRef' > ,
72
71
getNativeScrollRef : $PropertyType < ScrollView , 'getNativeScrollRef' > ,
73
- setNativeProps : $PropertyType < ScrollView , 'setNativeProps' > ,
74
72
scrollTo : $PropertyType < ScrollView , 'scrollTo' > ,
73
+ scrollToEnd : $PropertyType < ScrollView , 'scrollToEnd' > ,
75
74
flashScrollIndicators : $PropertyType < ScrollView , 'flashScrollIndicators' > ,
76
- ...typeof ScrollResponder . Mixin ,
77
- ...
78
- } ;
75
+
76
+ // ScrollResponder.Mixin public methods
77
+ scrollResponderZoomTo : $PropertyType <
78
+ typeof ScrollResponder . Mixin ,
79
+ 'scrollResponderZoomTo' ,
80
+ > ,
81
+ scrollResponderScrollNativeHandleToKeyboard : $PropertyType <
82
+ typeof ScrollResponder . Mixin ,
83
+ 'scrollResponderScrollNativeHandleToKeyboard' ,
84
+ > ,
85
+ | } > ;
86
+
87
+ export type ScrollResponderType = ScrollViewImperativeMethods ;
79
88
80
89
type IOSProps = $ReadOnly < { |
81
90
/**
@@ -581,6 +590,14 @@ export type Props = $ReadOnly<{|
581
590
* instead of calling `getInnerViewRef`.
582
591
*/
583
592
innerViewRef ?: React . Ref < typeof View > ,
593
+ /**
594
+ * A ref to the Native ScrollView component. This ref can be used to call
595
+ * all of ScrollView's public methods, in addition to native methods like
596
+ * measure, measureLayout, etc.
597
+ */
598
+ scrollViewRef ?: React . Ref <
599
+ typeof ScrollViewNativeComponent & ScrollViewImperativeMethods ,
600
+ > ,
584
601
| } > ;
585
602
586
603
type State = { |
@@ -603,11 +620,14 @@ function createScrollResponder(
603
620
}
604
621
605
622
type ContextType = { | horizontal : boolean | } | null ;
606
- const Context = React . createContext < ContextType > ( null ) ;
623
+ const Context : React . Context < ContextType > = React . createContext ( null ) ;
607
624
const standardHorizontalContext : ContextType = Object . freeze ( {
608
625
horizontal : true ,
609
626
} ) ;
610
627
const standardVerticalContext : ContextType = Object . freeze ( { horizontal : false } ) ;
628
+ type ScrollViewComponentStatics = $ReadOnly < { |
629
+ Context : typeof Context ,
630
+ | } > ;
611
631
612
632
/**
613
633
* Component that wraps platform ScrollView while providing
@@ -750,24 +770,64 @@ class ScrollView extends React.Component<Props, State> {
750
770
}
751
771
}
752
772
753
- setNativeProps ( props : { [ key : string ] : mixed , ...} ) {
754
- this . _scrollViewRef && this . _scrollViewRef . setNativeProps ( props ) ;
755
- }
773
+ _setNativeRef = setAndForwardRef ( {
774
+ getForwardedRef : ( ) => this . props . scrollViewRef ,
775
+ setLocalRef : ref => {
776
+ this . _scrollViewRef = ref ;
777
+
778
+ /*
779
+ This is a hack. Ideally we would forwardRef to the underlying
780
+ host component. However, since ScrollView has it's own methods that can be
781
+ called as well, if we used the standard forwardRef then these
782
+ methods wouldn't be accessible and thus be a breaking change.
783
+
784
+ Therefore we edit ref to include ScrollView's public methods so that
785
+ they are callable from the ref.
786
+ */
787
+ if ( ref ) {
788
+ ref . getScrollResponder = this . getScrollResponder ;
789
+ ref . getScrollableNode = this . getScrollableNode ;
790
+ ref . getInnerViewNode = this . getInnerViewNode ;
791
+ ref . getInnerViewRef = this . getInnerViewRef ;
792
+ ref . getNativeScrollRef = this . getNativeScrollRef ;
793
+ ref . scrollTo = this . scrollTo ;
794
+ ref . scrollToEnd = this . scrollToEnd ;
795
+ ref . flashScrollIndicators = this . flashScrollIndicators ;
796
+
797
+ // $FlowFixMe - This method was manually bound from ScrollResponder.mixin
798
+ ref . scrollResponderZoomTo = this . scrollResponderZoomTo ;
799
+ // $FlowFixMe - This method was manually bound from ScrollResponder.mixin
800
+ ref . scrollResponderScrollNativeHandleToKeyboard = this . scrollResponderScrollNativeHandleToKeyboard ;
801
+ }
802
+ } ,
803
+ } ) ;
756
804
757
805
/**
758
806
* Returns a reference to the underlying scroll responder, which supports
759
807
* operations like `scrollTo`. All ScrollView-like components should
760
808
* implement this method so that they can be composed while providing access
761
809
* to the underlying scroll responder's methods.
762
810
*/
763
- getScrollResponder ( ) : ScrollResponderType {
811
+ getScrollResponder : ( ) => ScrollResponderType = ( ) => {
812
+ if ( __DEV__ ) {
813
+ console . warn (
814
+ '`getScrollResponder()` is deprecated. This will be removed in a future release. ' +
815
+ 'Use <ScrollView ref={myRef} /> instead.' ,
816
+ ) ;
817
+ }
764
818
// $FlowFixMe - overriding type to include ScrollResponder.Mixin
765
819
return ( ( this : any ) : ScrollResponderType ) ;
766
- }
820
+ } ;
767
821
768
- getScrollableNode ( ) : ?number {
822
+ getScrollableNode : ( ) => ?number = ( ) => {
823
+ if ( __DEV__ ) {
824
+ console . warn (
825
+ '`getScrollableNode()` is deprecated. This will be removed in a future release. ' +
826
+ 'Use <ScrollView ref={myRef} /> instead.' ,
827
+ ) ;
828
+ }
769
829
return ReactNative . findNodeHandle ( this . _scrollViewRef ) ;
770
- }
830
+ } ;
771
831
772
832
getInnerViewNode ( ) : ?number {
773
833
console . warn (
@@ -785,9 +845,15 @@ class ScrollView extends React.Component<Props, State> {
785
845
return this . _innerViewRef ;
786
846
}
787
847
788
- getNativeScrollRef ( ) : ?React . ElementRef < HostComponent < mixed >> {
848
+ getNativeScrollRef : ( ) => ?React . ElementRef < HostComponent < mixed >> = ( ) => {
849
+ if ( __DEV__ ) {
850
+ console . warn (
851
+ '`getNativeScrollRef()` is deprecated. This will be removed in a future release. ' +
852
+ 'Use <ScrollView ref={myRef} /> instead.' ,
853
+ ) ;
854
+ }
789
855
return this . _scrollViewRef ;
790
- }
856
+ } ;
791
857
792
858
/**
793
859
* Scrolls to a given x, y offset, either immediately or with a smooth animation.
@@ -800,7 +866,7 @@ class ScrollView extends React.Component<Props, State> {
800
866
* the function also accepts separate arguments as an alternative to the options object.
801
867
* This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED.
802
868
*/
803
- scrollTo (
869
+ scrollTo : (
804
870
options ?:
805
871
| {
806
872
x ?: number ,
@@ -811,7 +877,18 @@ class ScrollView extends React.Component<Props, State> {
811
877
| number ,
812
878
deprecatedX ?: number ,
813
879
deprecatedAnimated ?: boolean ,
814
- ) {
880
+ ) => void = (
881
+ options ?:
882
+ | {
883
+ x ?: number ,
884
+ y ?: number ,
885
+ animated ?: boolean ,
886
+ ...
887
+ }
888
+ | number ,
889
+ deprecatedX ? : number ,
890
+ deprecatedAnimated ? : boolean ,
891
+ ) => {
815
892
let x , y, animated;
816
893
if ( typeof options === 'number' ) {
817
894
console . warn (
@@ -831,7 +908,7 @@ class ScrollView extends React.Component<Props, State> {
831
908
y : y || 0 ,
832
909
animated : animated !== false ,
833
910
} ) ;
834
- }
911
+ } ;
835
912
836
913
/**
837
914
* If this is a vertical ScrollView scrolls to the bottom.
@@ -841,22 +918,24 @@ class ScrollView extends React.Component<Props, State> {
841
918
* `scrollToEnd({animated: false})` for immediate scrolling.
842
919
* If no options are passed, `animated` defaults to true.
843
920
*/
844
- scrollToEnd ( options ?: ?{ animated ?: boolean , ...} ) {
921
+ scrollToEnd : ( options ?: ?{ animated ?: boolean , ...} ) => void = (
922
+ options ?: ?{ animated ?: boolean , ...} ,
923
+ ) => {
845
924
// Default to true
846
925
const animated = ( options && options . animated ) !== false ;
847
926
this . _scrollResponder . scrollResponderScrollToEnd ( {
848
927
animated : animated ,
849
928
} ) ;
850
- }
929
+ } ;
851
930
852
931
/**
853
932
* Displays the scroll indicators momentarily.
854
933
*
855
934
* @platform ios
856
935
*/
857
- flashScrollIndicators ( ) {
936
+ flashScrollIndicators : ( ) => void = ( ) => {
858
937
this . _scrollResponder . scrollResponderFlashScrollIndicators ( ) ;
859
- }
938
+ } ;
860
939
861
940
_getKeyForIndex ( index , childArray ) {
862
941
const child = childArray [ index ] ;
@@ -959,9 +1038,6 @@ class ScrollView extends React.Component<Props, State> {
959
1038
} ;
960
1039
961
1040
_scrollViewRef : ?React . ElementRef < HostComponent < mixed >> = null ;
962
- _setScrollViewRef = ( ref : ?React . ElementRef < HostComponent < mixed >> ) => {
963
- this. _scrollViewRef = ref ;
964
- } ;
965
1041
966
1042
_innerViewRef : ?React . ElementRef < typeof View > = null ;
967
1043
_setInnerViewRef = setAndForwardRef ( {
@@ -1182,7 +1258,7 @@ class ScrollView extends React.Component<Props, State> {
1182
1258
/* $FlowFixMe(>=0.117.0 site=react_native_fb) This comment suppresses
1183
1259
* an error found when Flow v0.117 was deployed. To see the error,
1184
1260
* delete this comment and run Flow. */
1185
- < ScrollViewClass { ...props } ref = { this . _setScrollViewRef } >
1261
+ < ScrollViewClass { ...props } ref = { this . _setNativeRef } >
1186
1262
{ Platform . isTV ? null : refreshControl }
1187
1263
{ contentContainer }
1188
1264
</ ScrollViewClass >
@@ -1200,14 +1276,14 @@ class ScrollView extends React.Component<Props, State> {
1200
1276
< ScrollViewClass
1201
1277
{ ...props }
1202
1278
style = { [ baseStyle , inner ] }
1203
- ref = { this . _setScrollViewRef } >
1279
+ ref = { this . _setNativeRef } >
1204
1280
{ contentContainer }
1205
1281
</ ScrollViewClass > ,
1206
1282
) ;
1207
1283
}
1208
1284
}
1209
1285
return (
1210
- < ScrollViewClass { ...props } ref = { this . _setScrollViewRef } >
1286
+ < ScrollViewClass { ...props } ref = { this . _setNativeRef } >
1211
1287
{ contentContainer }
1212
1288
</ ScrollViewClass >
1213
1289
) ;
@@ -1232,4 +1308,22 @@ const styles = StyleSheet.create({
1232
1308
} ,
1233
1309
} ) ;
1234
1310
1235
- module . exports = ScrollView ;
1311
+ function Wrapper ( props , ref ) {
1312
+ return < ScrollView { ...props } scrollViewRef = { ref } / > ;
1313
+ }
1314
+ Wrapper . displayName = 'ScrollView' ;
1315
+ const ForwardedScrollView = React . forwardRef ( Wrapper ) ;
1316
+
1317
+ // $FlowFixMe Add static context to ForwardedScrollView
1318
+ ForwardedScrollView . Context = Context ;
1319
+
1320
+ ForwardedScrollView . displayName = 'ScrollView' ;
1321
+
1322
+ module . exports = ( ( ForwardedScrollView : $FlowFixMe ) : React . AbstractComponent <
1323
+ React . ElementConfig < typeof ScrollView > ,
1324
+ $ReadOnly < { |
1325
+ ...$Exact < React . ElementRef < HostComponent < mixed >>> ,
1326
+ ...ScrollViewImperativeMethods ,
1327
+ | } > ,
1328
+ > &
1329
+ ScrollViewComponentStatics ) ;
0 commit comments