@@ -62,20 +62,29 @@ if (Platform.OS === 'android') {
6262 RCTScrollContentView = ScrollContentViewNativeComponent ;
6363}
6464
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' > ,
6968 getScrollableNode : $PropertyType < ScrollView , 'getScrollableNode' > ,
7069 getInnerViewNode : $PropertyType < ScrollView , 'getInnerViewNode' > ,
7170 getInnerViewRef : $PropertyType < ScrollView , 'getInnerViewRef' > ,
7271 getNativeScrollRef : $PropertyType < ScrollView , 'getNativeScrollRef' > ,
73- setNativeProps : $PropertyType < ScrollView , 'setNativeProps' > ,
7472 scrollTo : $PropertyType < ScrollView , 'scrollTo' > ,
73+ scrollToEnd : $PropertyType < ScrollView , 'scrollToEnd' > ,
7574 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 ;
7988
8089type IOSProps = $ReadOnly < { |
8190 /**
@@ -581,6 +590,14 @@ export type Props = $ReadOnly<{|
581590 * instead of calling `getInnerViewRef`.
582591 */
583592 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+ > ,
584601| } > ;
585602
586603type State = { |
@@ -603,11 +620,14 @@ function createScrollResponder(
603620}
604621
605622type ContextType = { | horizontal : boolean | } | null ;
606- const Context = React . createContext < ContextType > ( null ) ;
623+ const Context : React . Context < ContextType > = React . createContext ( null ) ;
607624const standardHorizontalContext : ContextType = Object . freeze ( {
608625 horizontal : true ,
609626} ) ;
610627const standardVerticalContext : ContextType = Object . freeze ( { horizontal : false } ) ;
628+ type ScrollViewComponentStatics = $ReadOnly < { |
629+ Context : typeof Context ,
630+ | } > ;
611631
612632/**
613633 * Component that wraps platform ScrollView while providing
@@ -750,24 +770,64 @@ class ScrollView extends React.Component<Props, State> {
750770 }
751771 }
752772
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+ } ) ;
756804
757805 /**
758806 * Returns a reference to the underlying scroll responder, which supports
759807 * operations like `scrollTo`. All ScrollView-like components should
760808 * implement this method so that they can be composed while providing access
761809 * to the underlying scroll responder's methods.
762810 */
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+ }
764818 // $FlowFixMe - overriding type to include ScrollResponder.Mixin
765819 return ( ( this : any ) : ScrollResponderType ) ;
766- }
820+ } ;
767821
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+ }
769829 return ReactNative . findNodeHandle ( this . _scrollViewRef ) ;
770- }
830+ } ;
771831
772832 getInnerViewNode ( ) : ?number {
773833 console . warn (
@@ -785,9 +845,15 @@ class ScrollView extends React.Component<Props, State> {
785845 return this . _innerViewRef ;
786846 }
787847
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+ }
789855 return this . _scrollViewRef ;
790- }
856+ } ;
791857
792858 /**
793859 * 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> {
800866 * the function also accepts separate arguments as an alternative to the options object.
801867 * This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED.
802868 */
803- scrollTo (
869+ scrollTo : (
804870 options ?:
805871 | {
806872 x ?: number ,
@@ -811,7 +877,18 @@ class ScrollView extends React.Component<Props, State> {
811877 | number ,
812878 deprecatedX ?: number ,
813879 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+ ) => {
815892 let x , y, animated;
816893 if ( typeof options === 'number' ) {
817894 console . warn (
@@ -831,7 +908,7 @@ class ScrollView extends React.Component<Props, State> {
831908 y : y || 0 ,
832909 animated : animated !== false ,
833910 } ) ;
834- }
911+ } ;
835912
836913 /**
837914 * If this is a vertical ScrollView scrolls to the bottom.
@@ -841,22 +918,24 @@ class ScrollView extends React.Component<Props, State> {
841918 * `scrollToEnd({animated: false})` for immediate scrolling.
842919 * If no options are passed, `animated` defaults to true.
843920 */
844- scrollToEnd ( options ?: ?{ animated ?: boolean , ...} ) {
921+ scrollToEnd : ( options ?: ?{ animated ?: boolean , ...} ) => void = (
922+ options ?: ?{ animated ?: boolean , ...} ,
923+ ) => {
845924 // Default to true
846925 const animated = ( options && options . animated ) !== false ;
847926 this . _scrollResponder . scrollResponderScrollToEnd ( {
848927 animated : animated ,
849928 } ) ;
850- }
929+ } ;
851930
852931 /**
853932 * Displays the scroll indicators momentarily.
854933 *
855934 * @platform ios
856935 */
857- flashScrollIndicators ( ) {
936+ flashScrollIndicators : ( ) => void = ( ) => {
858937 this . _scrollResponder . scrollResponderFlashScrollIndicators ( ) ;
859- }
938+ } ;
860939
861940 _getKeyForIndex ( index , childArray ) {
862941 const child = childArray [ index ] ;
@@ -959,9 +1038,6 @@ class ScrollView extends React.Component<Props, State> {
9591038 } ;
9601039
9611040 _scrollViewRef : ?React . ElementRef < HostComponent < mixed >> = null ;
962- _setScrollViewRef = ( ref : ?React . ElementRef < HostComponent < mixed >> ) => {
963- this. _scrollViewRef = ref ;
964- } ;
9651041
9661042 _innerViewRef : ?React . ElementRef < typeof View > = null ;
9671043 _setInnerViewRef = setAndForwardRef ( {
@@ -1182,7 +1258,7 @@ class ScrollView extends React.Component<Props, State> {
11821258 /* $FlowFixMe(>=0.117.0 site=react_native_fb) This comment suppresses
11831259 * an error found when Flow v0.117 was deployed. To see the error,
11841260 * delete this comment and run Flow. */
1185- < ScrollViewClass { ...props } ref = { this . _setScrollViewRef } >
1261+ < ScrollViewClass { ...props } ref = { this . _setNativeRef } >
11861262 { Platform . isTV ? null : refreshControl }
11871263 { contentContainer }
11881264 </ ScrollViewClass >
@@ -1200,14 +1276,14 @@ class ScrollView extends React.Component<Props, State> {
12001276 < ScrollViewClass
12011277 { ...props }
12021278 style = { [ baseStyle , inner ] }
1203- ref = { this . _setScrollViewRef } >
1279+ ref = { this . _setNativeRef } >
12041280 { contentContainer }
12051281 </ ScrollViewClass > ,
12061282 ) ;
12071283 }
12081284 }
12091285 return (
1210- < ScrollViewClass { ...props } ref = { this . _setScrollViewRef } >
1286+ < ScrollViewClass { ...props } ref = { this . _setNativeRef } >
12111287 { contentContainer }
12121288 </ ScrollViewClass >
12131289 ) ;
@@ -1232,4 +1308,22 @@ const styles = StyleSheet.create({
12321308 } ,
12331309} ) ;
12341310
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