From 8c2a4d0d26dbfcb026aee4628a5458e7d22092b8 Mon Sep 17 00:00:00 2001 From: Mike Vitousek Date: Fri, 11 Nov 2022 17:04:38 -0800 Subject: [PATCH] Annotate React hooks in xplat, defaulting to any Summary: Add explicit annotations to React hook callbacks as required for Flow's Local Type Inference project. This codemod prepares the codebase to match Flow's new typechecking algorithm. The new algorithm will make Flow more reliable and predictable. This diff adds `any` or `$FlowFixMe` in cases where more precise types could not be determined. Details: - Codemod script: `.facebook/flowd codemod annotate-react-hooks ../../xplat/js --default-any --write` - Local Type Inference announcement: [post](https://fb.workplace.com/groups/flowlang/posts/788206301785035) - Support group: [Flow Support](https://fb.workplace.com/groups/flow) drop-conflicts bypass-lint Reviewed By: SamChou19815 Differential Revision: D41231214 fbshipit-source-id: d5f5ce8d61020baa1138292c9e9f1c69dffd324c --- .../ScrollView/ScrollViewStickyHeader.js | 2 +- packages/rn-tester/js/RNTesterAppShared.js | 31 +++++++------- .../ActivityIndicatorExample.js | 5 ++- .../DrawerLayoutAndroidExample.js | 7 ++-- ...PointerEventAttributesHoverablePointers.js | 27 ++++++++---- .../PointerEventAttributesNoHoverPointers.js | 27 ++++++++---- .../PointerEventPointerOverOut.js | 41 ++++++++++++++----- .../FlatList/FlatList-onEndReached.js | 3 +- .../FlatList-onViewableItemsChanged.js | 7 ++-- .../FlatList/FlatList-withSeparators.js | 5 ++- .../js/examples/Pressable/PressableExample.js | 2 +- .../ScrollViewPressableStickyHeaderExample.js | 12 +++--- .../SectionList/SectionList-onEndReached.js | 2 +- .../SectionList-onViewableItemsChanged.js | 5 ++- .../SectionList/SectionList-withSeparators.js | 4 +- 15 files changed, 116 insertions(+), 64 deletions(-) diff --git a/Libraries/Components/ScrollView/ScrollViewStickyHeader.js b/Libraries/Components/ScrollView/ScrollViewStickyHeader.js index c366f3c8887..9d59cf527f1 100644 --- a/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +++ b/Libraries/Components/ScrollView/ScrollViewStickyHeader.js @@ -134,7 +134,7 @@ const ScrollViewStickyHeaderWithForwardedRef: React.AbstractComponent< // platform to JS, so we need the ShadowTree to have knowledge // of the current position. const animatedValueListener = useCallback( - ({value}) => { + ({value}: $FlowFixMe) => { const _debounceTimeout: number = Platform.OS === 'android' ? 15 : 64; // When the AnimatedInterpolation is recreated, it always initializes // to a value of zero and emits a value change of 0 to its listeners. diff --git a/packages/rn-tester/js/RNTesterAppShared.js b/packages/rn-tester/js/RNTesterAppShared.js index cec3abe635c..3cd8e9d9afa 100644 --- a/packages/rn-tester/js/RNTesterAppShared.js +++ b/packages/rn-tester/js/RNTesterAppShared.js @@ -8,25 +8,24 @@ * @flow */ -import {BackHandler, StyleSheet, useColorScheme, View} from 'react-native'; -import * as React from 'react'; - +import {RNTesterEmptyBookmarksState} from './components/RNTesterEmptyBookmarksState'; import RNTesterModuleContainer from './components/RNTesterModuleContainer'; import RNTesterModuleList from './components/RNTesterModuleList'; import RNTesterNavBar, {navBarHeight} from './components/RNTesterNavbar'; -import RNTesterList from './utils/RNTesterList'; -import { - Screens, - initialNavigationState, - getExamplesListWithBookmarksAndRecentlyUsed, -} from './utils/testerStateUtils'; -import { - RNTesterNavigationReducer, - RNTesterNavigationActionsType, -} from './utils/RNTesterNavigationReducer'; import {RNTesterThemeContext, themes} from './components/RNTesterTheme'; import RNTTitleBar from './components/RNTTitleBar'; -import {RNTesterEmptyBookmarksState} from './components/RNTesterEmptyBookmarksState'; +import RNTesterList from './utils/RNTesterList'; +import { + RNTesterNavigationActionsType, + RNTesterNavigationReducer, +} from './utils/RNTesterNavigationReducer'; +import { + Screens, + getExamplesListWithBookmarksAndRecentlyUsed, + initialNavigationState, +} from './utils/testerStateUtils'; +import * as React from 'react'; +import {BackHandler, StyleSheet, View, useColorScheme} from 'react-native'; // RNTester App currently uses in memory storage for storing navigation state @@ -79,7 +78,7 @@ const RNTesterApp = (): React.Node => { }, [activeModuleKey, handleBackPress]); const handleModuleCardPress = React.useCallback( - ({exampleType, key, title}) => { + ({exampleType, key, title}: any) => { dispatch({ type: RNTesterNavigationActionsType.MODULE_CARD_PRESS, data: {exampleType, key, title}, @@ -99,7 +98,7 @@ const RNTesterApp = (): React.Node => { ); const toggleBookmark = React.useCallback( - ({exampleType, key}) => { + ({exampleType, key}: any) => { dispatch({ type: RNTesterNavigationActionsType.BOOKMARK_PRESS, data: {exampleType, key}, diff --git a/packages/rn-tester/js/examples/ActivityIndicator/ActivityIndicatorExample.js b/packages/rn-tester/js/examples/ActivityIndicator/ActivityIndicatorExample.js index 2713fce143f..b2d7c9e8ad8 100644 --- a/packages/rn-tester/js/examples/ActivityIndicator/ActivityIndicatorExample.js +++ b/packages/rn-tester/js/examples/ActivityIndicator/ActivityIndicatorExample.js @@ -9,11 +9,12 @@ */ import type {Node} from 'React'; + +import React, {useCallback, useEffect, useRef, useState} from 'react'; import {ActivityIndicator, StyleSheet, View} from 'react-native'; -import React, {useState, useCallback, useRef, useEffect} from 'react'; function ToggleAnimatingActivityIndicator() { - const timer = useRef(); + const timer = useRef(); const [animating, setAnimating] = useState(true); diff --git a/packages/rn-tester/js/examples/DrawerLayoutAndroid/DrawerLayoutAndroidExample.js b/packages/rn-tester/js/examples/DrawerLayoutAndroid/DrawerLayoutAndroidExample.js index 2906099c49d..f760f66969e 100644 --- a/packages/rn-tester/js/examples/DrawerLayoutAndroid/DrawerLayoutAndroidExample.js +++ b/packages/rn-tester/js/examples/DrawerLayoutAndroid/DrawerLayoutAndroidExample.js @@ -10,18 +10,19 @@ 'use strict'; -import React, {useRef, useState} from 'react'; import type {Node} from 'react'; + +import React, {useRef, useState} from 'react'; import { Button, DrawerLayoutAndroid, - Text, StyleSheet, + Text, View, } from 'react-native'; const Drawer = () => { - const drawer = useRef(null); + const drawer = useRef>(null); const [drawerPosition, setDrawerPosition] = useState('left'); const changeDrawerPosition = () => { if (drawerPosition === 'left') { diff --git a/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventAttributesHoverablePointers.js b/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventAttributesHoverablePointers.js index 6582d9f3483..384430805e1 100644 --- a/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventAttributesHoverablePointers.js +++ b/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventAttributesHoverablePointers.js @@ -8,18 +8,19 @@ * @flow */ +import type {PlatformTestComponentBaseProps} from '../PlatformTest/RNTesterPlatformTestTypes'; +import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; +import type {HostComponent} from 'react-native/Libraries/Renderer/shims/ReactNativeTypes'; import type { Layout, PointerEvent, } from 'react-native/Libraries/Types/CoreEventTypes'; -import type {PlatformTestComponentBaseProps} from '../PlatformTest/RNTesterPlatformTestTypes'; - -import * as React from 'react'; -import {useCallback, useRef, useState} from 'react'; -import {View, StyleSheet} from 'react-native'; import RNTesterPlatformTest from '../PlatformTest/RNTesterPlatformTest'; import {check_PointerEvent, useTestEventHandler} from './PointerEventSupport'; +import * as React from 'react'; +import {useCallback, useRef, useState} from 'react'; +import {StyleSheet, View} from 'react-native'; const eventList = [ 'pointerOver', @@ -168,7 +169,13 @@ function PointerEventAttributesHoverablePointersTestCase( [harness], ); - const square1Ref = useRef(); + const square1Ref = + useRef>, + >, + >>(); const square1Handlers = useTestEventHandler(eventList, (event, eventType) => { if (!square1Visible) { return; @@ -197,7 +204,13 @@ function PointerEventAttributesHoverablePointersTestCase( } }); - const square2Ref = useRef(); + const square2Ref = + useRef>, + >, + >>(); const square2Handlers = useTestEventHandler(eventList, (event, eventType) => { const square2Elem = square2Ref.current; if (square2Elem != null) { diff --git a/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventAttributesNoHoverPointers.js b/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventAttributesNoHoverPointers.js index 5369a55aba0..bedfc48181a 100644 --- a/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventAttributesNoHoverPointers.js +++ b/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventAttributesNoHoverPointers.js @@ -8,18 +8,19 @@ * @flow */ +import type {PlatformTestComponentBaseProps} from '../PlatformTest/RNTesterPlatformTestTypes'; +import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; +import type {HostComponent} from 'react-native/Libraries/Renderer/shims/ReactNativeTypes'; import type { Layout, PointerEvent, } from 'react-native/Libraries/Types/CoreEventTypes'; -import type {PlatformTestComponentBaseProps} from '../PlatformTest/RNTesterPlatformTestTypes'; - -import * as React from 'react'; -import {useCallback, useRef, useState} from 'react'; -import {View, StyleSheet} from 'react-native'; import RNTesterPlatformTest from '../PlatformTest/RNTesterPlatformTest'; import {check_PointerEvent, useTestEventHandler} from './PointerEventSupport'; +import * as React from 'react'; +import {useCallback, useRef, useState} from 'react'; +import {StyleSheet, View} from 'react-native'; const eventList = [ 'pointerOver', @@ -136,7 +137,13 @@ function PointerEventAttributesNoHoverPointersTestCase( [harness], ); - const square1Ref = useRef(); + const square1Ref = + useRef>, + >, + >>(); const square1Handlers = useTestEventHandler(eventList, (event, eventType) => { if (!square1Visible) { return; @@ -165,7 +172,13 @@ function PointerEventAttributesNoHoverPointersTestCase( } }); - const square2Ref = useRef(); + const square2Ref = + useRef>, + >, + >>(); const square2Handlers = useTestEventHandler(eventList, (event, eventType) => { const square2Elem = square2Ref.current; if (square2Elem != null) { diff --git a/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventPointerOverOut.js b/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventPointerOverOut.js index 8b1046a760b..16ed3b1f5a2 100644 --- a/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventPointerOverOut.js +++ b/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventPointerOverOut.js @@ -9,12 +9,13 @@ */ import type {PlatformTestComponentBaseProps} from '../PlatformTest/RNTesterPlatformTestTypes'; -import type {PointerEvent} from 'react-native/Libraries/Types/CoreEventTypes'; +import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes'; import type {HostComponent} from 'react-native/Libraries/Renderer/shims/ReactNativeTypes'; +import type {PointerEvent} from 'react-native/Libraries/Types/CoreEventTypes'; import RNTesterPlatformTest from '../PlatformTest/RNTesterPlatformTest'; import * as React from 'react'; -import {useRef, useCallback} from 'react'; +import {useCallback, useRef} from 'react'; import {StyleSheet, View} from 'react-native'; function getNativeTagFromHostElement( @@ -59,14 +60,34 @@ function PointerEventPointerOverOutTestCase( const innerNativeTagRef = useRef(-1); const outerNativeTagRef = useRef(-1); - const handleInnerRefCallback = useCallback(elem => { - const nativeTag = getNativeTagFromHostElement(elem); - innerNativeTagRef.current = nativeTag != null ? nativeTag : -1; - }, []); - const handleOuterRefCallback = useCallback(elem => { - const nativeTag = getNativeTagFromHostElement(elem); - outerNativeTagRef.current = nativeTag != null ? nativeTag : -1; - }, []); + const handleInnerRefCallback = useCallback( + ( + elem: null | React$ElementRef< + React$AbstractComponent< + ViewProps, + React.ElementRef>, + >, + >, + ) => { + const nativeTag = getNativeTagFromHostElement(elem); + innerNativeTagRef.current = nativeTag != null ? nativeTag : -1; + }, + [], + ); + const handleOuterRefCallback = useCallback( + ( + elem: null | React$ElementRef< + React$AbstractComponent< + ViewProps, + React.ElementRef>, + >, + >, + ) => { + const nativeTag = getNativeTagFromHostElement(elem); + outerNativeTagRef.current = nativeTag != null ? nativeTag : -1; + }, + [], + ); const innerOverRef = useRef(0); const innerOutRef = useRef(0); diff --git a/packages/rn-tester/js/examples/FlatList/FlatList-onEndReached.js b/packages/rn-tester/js/examples/FlatList/FlatList-onEndReached.js index 7d5c0437d3e..792b63f677c 100644 --- a/packages/rn-tester/js/examples/FlatList/FlatList-onEndReached.js +++ b/packages/rn-tester/js/examples/FlatList/FlatList-onEndReached.js @@ -10,6 +10,7 @@ 'use strict'; import type {RNTesterModuleExample} from '../../types/RNTesterTypes'; + import BaseFlatListExample from './BaseFlatListExample'; import * as React from 'react'; @@ -20,7 +21,7 @@ export function FlatList_onEndReached(): React.Node { setOutput('onEndReached'), onEndReachedThreshold: 0, }; - const ref = React.useRef(null); + const ref = React.useRef(null); const onTest = () => { const scrollResponder = ref?.current?.getScrollResponder(); diff --git a/packages/rn-tester/js/examples/FlatList/FlatList-onViewableItemsChanged.js b/packages/rn-tester/js/examples/FlatList/FlatList-onViewableItemsChanged.js index 981d226dc1e..76e29fac105 100644 --- a/packages/rn-tester/js/examples/FlatList/FlatList-onViewableItemsChanged.js +++ b/packages/rn-tester/js/examples/FlatList/FlatList-onViewableItemsChanged.js @@ -10,11 +10,12 @@ 'use strict'; -import type {RNTesterModuleExample} from '../../types/RNTesterTypes'; import type {ViewToken} from '../../../../../Libraries/Lists/ViewabilityHelper'; +import type {RNTesterModuleExample} from '../../types/RNTesterTypes'; + import BaseFlatListExample from './BaseFlatListExample'; -import {StyleSheet, View, FlatList} from 'react-native'; import * as React from 'react'; +import {FlatList, StyleSheet, View} from 'react-native'; type FlatListProps = React.ElementProps; type ViewabilityConfig = $PropertyType; @@ -49,7 +50,7 @@ export function FlatList_onViewableItemsChanged(props: { horizontal, }; - const ref = React.useRef(null); + const ref = React.useRef(null); const onTest = useScrollRefScroll === true ? () => { diff --git a/packages/rn-tester/js/examples/FlatList/FlatList-withSeparators.js b/packages/rn-tester/js/examples/FlatList/FlatList-withSeparators.js index 9f8a8881bb8..c7d562dbfb0 100644 --- a/packages/rn-tester/js/examples/FlatList/FlatList-withSeparators.js +++ b/packages/rn-tester/js/examples/FlatList/FlatList-withSeparators.js @@ -10,9 +10,10 @@ 'use strict'; import type {RNTesterModuleExample} from '../../types/RNTesterTypes'; + import BaseFlatListExample from './BaseFlatListExample'; -import {StyleSheet, View, Text} from 'react-native'; import * as React from 'react'; +import {StyleSheet, Text, View} from 'react-native'; const Separator = (defaultColor: string, highlightColor: string) => @@ -41,7 +42,7 @@ export function FlatList_withSeparators(): React.Node { const exampleProps = { ItemSeparatorComponent: Separator('lightgreen', 'green'), }; - const ref = React.useRef(null); + const ref = React.useRef<$FlowFixMe>(null); return ; } diff --git a/packages/rn-tester/js/examples/Pressable/PressableExample.js b/packages/rn-tester/js/examples/Pressable/PressableExample.js index bc3689ba577..85bd8cb19e6 100644 --- a/packages/rn-tester/js/examples/Pressable/PressableExample.js +++ b/packages/rn-tester/js/examples/Pressable/PressableExample.js @@ -226,7 +226,7 @@ function PressableHitSlop() { function PressableNativeMethods() { const [status, setStatus] = useState(null); - const ref = useRef(null); + const ref = useRef<$FlowFixMe>(null); useEffect(() => { setStatus(ref.current != null && typeof ref.current.measure === 'function'); diff --git a/packages/rn-tester/js/examples/ScrollView/ScrollViewPressableStickyHeaderExample.js b/packages/rn-tester/js/examples/ScrollView/ScrollViewPressableStickyHeaderExample.js index 3c01f4f6e02..854e64da95d 100644 --- a/packages/rn-tester/js/examples/ScrollView/ScrollViewPressableStickyHeaderExample.js +++ b/packages/rn-tester/js/examples/ScrollView/ScrollViewPressableStickyHeaderExample.js @@ -8,15 +8,15 @@ * @format */ +import * as React from 'react'; import { - StyleSheet, - View, - Text, + Button, Pressable, ScrollView, - Button, + StyleSheet, + Text, + View, } from 'react-native'; -import * as React from 'react'; function StickyHeader() { const [backgroundColor, setBackgroundColor] = React.useState('blue'); @@ -51,7 +51,7 @@ function renderComponent1(i: number) { } export default function ScrollViewPressableStickyHeaderExample(): React.Node { - const scrollRef = React.useRef(null); + const scrollRef = React.useRef<$FlowFixMe>(null); const components = []; for (var i = 1; i < 10; i++) { components.push(renderComponent1(i)); diff --git a/packages/rn-tester/js/examples/SectionList/SectionList-onEndReached.js b/packages/rn-tester/js/examples/SectionList/SectionList-onEndReached.js index 498f0c4e8d9..1f7794e8b23 100644 --- a/packages/rn-tester/js/examples/SectionList/SectionList-onEndReached.js +++ b/packages/rn-tester/js/examples/SectionList/SectionList-onEndReached.js @@ -18,7 +18,7 @@ export function SectionList_onEndReached(): React.Node { setOutput('onEndReached'), onEndReachedThreshold: 0, }; - const ref = React.useRef(null); + const ref = React.useRef(null); const onTest = () => { const scrollResponder = ref?.current?.getScrollResponder(); diff --git a/packages/rn-tester/js/examples/SectionList/SectionList-onViewableItemsChanged.js b/packages/rn-tester/js/examples/SectionList/SectionList-onViewableItemsChanged.js index f9399653088..61ee3b66e30 100644 --- a/packages/rn-tester/js/examples/SectionList/SectionList-onViewableItemsChanged.js +++ b/packages/rn-tester/js/examples/SectionList/SectionList-onViewableItemsChanged.js @@ -9,9 +9,10 @@ */ import type {ViewToken} from 'react-native/Libraries/Lists/ViewabilityHelper'; + import SectionListBaseExample from './SectionListBaseExample'; -import {View, StyleSheet, SectionList} from 'react-native'; import * as React from 'react'; +import {SectionList, StyleSheet, View} from 'react-native'; const VIEWABILITY_CONFIG = { minimumViewTime: 1000, @@ -45,7 +46,7 @@ export function SectionList_onViewableItemsChanged(props: { viewabilityConfig, horizontal, }; - const ref = React.useRef(null); + const ref = React.useRef(null); const onTest = useScrollRefScroll === true ? () => { diff --git a/packages/rn-tester/js/examples/SectionList/SectionList-withSeparators.js b/packages/rn-tester/js/examples/SectionList/SectionList-withSeparators.js index a203be61182..309517ccd03 100644 --- a/packages/rn-tester/js/examples/SectionList/SectionList-withSeparators.js +++ b/packages/rn-tester/js/examples/SectionList/SectionList-withSeparators.js @@ -9,8 +9,8 @@ */ import SectionListBaseExample from './SectionListBaseExample'; -import {View, Text, StyleSheet} from 'react-native'; import * as React from 'react'; +import {StyleSheet, Text, View} from 'react-native'; const Separator = (defaultColor: string, highlightColor: string, isSectionSeparator: boolean) => @@ -37,7 +37,7 @@ export function SectionList_withSeparators(): React.Node { ItemSeparatorComponent: Separator('lightgreen', 'green', false), SectionSeparatorComponent: Separator('lightblue', 'blue', true), }; - const ref = React.useRef(null); + const ref = React.useRef(null); return ; }