From 5162816e035f29ee1743cd00a3f93522b5c1abfe Mon Sep 17 00:00:00 2001 From: Jani Kinnunen Date: Mon, 11 May 2026 07:15:42 -0700 Subject: [PATCH] fix: fix getNativeScrollRef return type for FlatList (#54735) Summary: ### The Problem When trying to measure the location of a View within a FlatList (ie. for scrolling to the view), the current recommended method is to use measureLayout on the nested view to determine its location inside the containing FlatList: ``` const MyComponent = () => { const flatListRef = useRef(null); const nestedViewRef = useRef(null); const scrollToNestedView = () => { if (!flatListRef.current || !nestedViewRef.current) { return; } nestedViewRef.current.measureLayout( flatListRef.current.getNativeScrollRef(), (x, y) => { flatListRef.current.scrollTo({ y, animated: true }); }, ); } return ( { /* content */ } ); } ``` However the types for `FlatList` `getNativeScrollRef` don't allow this. ### The solution This solution is basically identical to that in https://github.com/facebook/react-native/issues/52203. The return value for `getNativeScrollRef` should be `HostInstance | null` ## Changelog:[GENERAL] [FIXED] - Change FlatList.getNativeScrollRef return type definition to allow accessing the underlying HostInstance. Pull Request resolved: https://github.com/facebook/react-native/pull/54735 Test Plan: None needed. This is only a type update exposing existing functionality. Reviewed By: zeyap Differential Revision: D104393366 Pulled By: huntie fbshipit-source-id: 700f708d9a39b16af3e0ed90a748051361101627 --- .../Components/ScrollView/ScrollView.d.ts | 89 +++++++++++-------- .../Libraries/Lists/FlatList.d.ts | 12 +-- 2 files changed, 58 insertions(+), 43 deletions(-) diff --git a/packages/react-native/Libraries/Components/ScrollView/ScrollView.d.ts b/packages/react-native/Libraries/Components/ScrollView/ScrollView.d.ts index bd9f15396e7..5fb44404655 100644 --- a/packages/react-native/Libraries/Components/ScrollView/ScrollView.d.ts +++ b/packages/react-native/Libraries/Components/ScrollView/ScrollView.d.ts @@ -264,7 +264,7 @@ interface ScrollResponderMixin extends SubscribableMixin { * down to make it meet the keyboard's top. Default is false. */ scrollResponderScrollNativeHandleToKeyboard( - nodeHandle: any, + nodeHandle: number | HostInstance, additionalOffset?: number, preventNegativeScrollOffset?: boolean, ): void; @@ -836,10 +836,29 @@ export interface ScrollViewProps StickyHeaderComponent?: React.ComponentType | undefined; } -declare class ScrollViewComponent extends React.Component {} -export declare const ScrollViewBase: Constructor & - typeof ScrollViewComponent; -export class ScrollView extends ScrollViewBase { +export interface ScrollViewScrollToOptions { + x?: number | undefined; + y?: number | undefined; + animated?: boolean | undefined; +} + +// Public methods for ScrollView +export interface ScrollViewImperativeMethods { + /** + * Returns a reference to the underlying scroll responder, which supports + * operations like `scrollTo`. All ScrollView-like components should + * implement this method so that they can be composed while providing access + * to the underlying scroll responder's methods. + */ + readonly getScrollResponder: () => ScrollResponderType; + readonly getScrollableNode: () => number | undefined; + readonly getInnerViewNode: () => number | undefined; + readonly getInnerViewRef: () => React.ComponentRef | null; + /** + * Returns a reference to the underlying native scroll view, or null if the + * native instance is not mounted. + */ + readonly getNativeScrollRef: () => HostInstance | null; /** * Scrolls to a given x, y offset, either immediately or with a smooth animation. * Syntax: @@ -850,18 +869,11 @@ export class ScrollView extends ScrollViewBase { * the function also accepts separate arguments as an alternative to the options object. * This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED. */ - scrollTo( - y?: - | number - | { - x?: number | undefined; - y?: number | undefined; - animated?: boolean | undefined; - }, + readonly scrollTo: ( + options?: ScrollViewScrollToOptions | number, deprecatedX?: number, deprecatedAnimated?: boolean, - ): void; - + ) => void; /** * A helper function that scrolls to the end of the scrollview; * If this is a vertical ScrollView, it scrolls to the bottom. @@ -870,32 +882,39 @@ export class ScrollView extends ScrollViewBase { * The options object has an animated prop, that enables the scrolling animation or not. * The animated prop defaults to true */ - scrollToEnd(options?: {animated?: boolean | undefined}): void; - + readonly scrollToEnd: (options?: ScrollViewScrollToOptions | null) => void; /** * Displays the scroll indicators momentarily. */ - flashScrollIndicators(): void; + readonly flashScrollIndicators: () => void; + scrollResponderZoomTo( + rect: { + x: number; + y: number; + width: number; + height: number; + animated?: boolean | undefined; + }, + animated?: boolean, // deprecated, put this inside the rect argument instead + ): void; + scrollResponderScrollNativeHandleToKeyboard( + nodeHandle: number | HostInstance, + additionalOffset?: number, + preventNegativeScrollOffset?: boolean, + ): void; +} - /** - * Returns a reference to the underlying scroll responder, which supports - * operations like `scrollTo`. All ScrollView-like components should - * implement this method so that they can be composed while providing access - * to the underlying scroll responder's methods. - */ - getScrollResponder(): ScrollResponderMixin; +export type ScrollResponderType = ScrollViewImperativeMethods; - getScrollableNode(): any; - - // Undocumented - getInnerViewNode(): any; - - /** - * Returns a reference to the underlying native scroll view, or null if the - * native instance is not mounted. - */ - getNativeScrollRef: () => HostInstance | null; +export interface PublicScrollViewInstance + extends HostInstance, + ScrollViewImperativeMethods {} +declare class ScrollViewComponent extends React.Component {} +export declare const ScrollViewBase: Constructor & + typeof ScrollViewComponent; +export interface ScrollView extends ScrollViewImperativeMethods {} +export class ScrollView extends ScrollViewBase { /** * @deprecated Use scrollTo instead */ diff --git a/packages/react-native/Libraries/Lists/FlatList.d.ts b/packages/react-native/Libraries/Lists/FlatList.d.ts index 06c4bca1f52..a1a8aa4cb73 100644 --- a/packages/react-native/Libraries/Lists/FlatList.d.ts +++ b/packages/react-native/Libraries/Lists/FlatList.d.ts @@ -14,10 +14,9 @@ import type { VirtualizedListProps, ViewabilityConfig, } from '@react-native/virtualized-lists'; -import type {ScrollViewComponent} from '../Components/ScrollView/ScrollView'; +import type {PublicScrollViewInstance} from '../Components/ScrollView/ScrollView'; import type {StyleProp} from '../StyleSheet/StyleSheet'; import type {ViewStyle} from '../StyleSheet/StyleSheetTypes'; -import type {View} from '../Components/View/View'; export interface FlatListProps extends VirtualizedListProps { /** @@ -229,13 +228,10 @@ export abstract class FlatListComponent< getScrollResponder: () => React.JSX.Element | null | undefined; /** - * Provides a reference to the underlying host component + * Returns a reference to the underlying native scroll view, or null if the + * native instance is not mounted. */ - getNativeScrollRef: () => - | React.ComponentRef - | React.ComponentRef - | null - | undefined; + getNativeScrollRef: () => PublicScrollViewInstance | null; getScrollableNode: () => any;