@samitouri / QOS-React / commits / 45804af18d

[flow] Eliminate usage of more than 1-arg `React.AbstractComponent` in React codebase (#31314)

<!-- Thanks for submitting a pull request! We appreciate you spending the time to work on these changes. Please provide enough information so that others can review your pull request. The three fields below are mandatory. Before submitting a pull request, please make sure the following is done: 1. Fork [the repository](https://github.com/facebook/react) and create your branch from `main`. 2. Run `yarn` in the repository root. 3. If you've fixed a bug or added code that should be tested, add tests! 4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch TestName` is helpful in development. 5. Run `yarn test --prod` to test in the production environment. It supports the same options as `yarn test`. 6. If you need a debugger, run `yarn test --debug --watch TestName`, open `chrome://inspect`, and press "Inspect". 7. Format your code with [prettier](https://github.com/prettier/prettier) (`yarn prettier`). 8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only check changed files. 9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`). 10. If you haven't already, complete the CLA. Learn more about contributing: https://reactjs.org/docs/how-to-contribute.html --> ## Summary In order to adopt react 19's ref-as-prop model, Flow needs to eliminate all the places where they are treated differently. `React.AbstractComponent` is the worst example of this, and we need to eliminate it. This PR eliminates them from the react repo, and only keeps the one that has 1 argument of props. ## How did you test this change? yarn flow

Sam Zhou committed Oct 21, 2024 at 16:17 UTC 45804af18d589fd2c181f3b020f07661c46b73ea
15 files changed +36 -38
.eslintrc.js
+1
@@ -569,6 +569,7 @@ module.exports = {
569 React$Node: 'readonly',
570 React$Portal: 'readonly',
571 React$Ref: 'readonly',
572 + React$RefSetter: 'readonly',
573 ReadableStreamController: 'readonly',
574 ReadableStreamReader: 'readonly',
575 RequestInfo: 'readonly',
packages/react-devtools-inline/src/frontend.js
+1 -1
@@ -52,7 +52,7 @@ export function initialize(
52 bridge?: FrontendBridge,
53 store?: Store,
54 } = {},
55 -): React.AbstractComponent<Props, mixed> {
55 +): React.ComponentType<Props> {
56 if (bridge == null) {
57 bridge = createBridge(contentWindow);
58 }
packages/react-devtools-shared/src/devtools/ContextMenu/types.js
+5 -3
@@ -7,7 +7,7 @@
7 * @flow
8 */
9
10 -import type {Node as ReactNode, AbstractComponent, ElementRef} from 'react';
10 +import type {Node as ReactNode} from 'react';
11
12 export type ContextMenuItem = {
13 onClick: () => void,
@@ -25,5 +25,7 @@ export type ContextMenuHandle = {
25 hide(): void,
26 };
27
28 -export type ContextMenuComponent = AbstractComponent<{}, ContextMenuHandle>;
29 -export type ContextMenuRef = {current: ElementRef<ContextMenuComponent> | null};
28 +/*::
29 +export type ContextMenuComponent = component(ref: React$RefSetter<ContextMenuHandle>);
30 +*/
31 +export type ContextMenuRef = {current: ContextMenuHandle | null};
packages/react-devtools-shared/src/devtools/views/Components/Components.js
+1 -1
@@ -246,4 +246,4 @@ function setResizeCSSVariable(
246 }
247 }
248
249 -export default (portaledContent(Components): React$AbstractComponent<{}>);
249 +export default (portaledContent(Components): React$ComponentType<{}>);
packages/react-devtools-shared/src/devtools/views/portaledContent.js
+2 -2
@@ -17,8 +17,8 @@ import ThemeProvider from './ThemeProvider';
17 export type Props = {portalContainer?: Element, ...};
18
19 export default function portaledContent(
20 - Component: React$AbstractComponent<any>,
21 -): React$AbstractComponent<any> {
20 + Component: React$ComponentType<any>,
21 +): React$ComponentType<any> {
22 return function PortaledContent({portalContainer, ...rest}: Props) {
23 const store = useContext(StoreContext);
24
packages/react-devtools-shell/src/app/InspectableElements/CustomHooks.js
+4 -2
@@ -72,7 +72,7 @@ function useDeepHookF() {
72 const ContextA = createContext('A');
73 const ContextB = createContext('B');
74
75 -function FunctionWithHooks(props: any, ref: React$Ref<any>) {
75 +function FunctionWithHooks(props: any, ref: React$RefSetter<any>) {
76 const [count, updateCount] = useState(0);
77 // eslint-disable-next-line no-unused-vars
78 const contextValueA = useContext(ContextA);
@@ -108,7 +108,9 @@ function FunctionWithHooks(props: any, ref: React$Ref<any>) {
108 const MemoWithHooks = memo(FunctionWithHooks);
109 const ForwardRefWithHooks = forwardRef(FunctionWithHooks);
110
111 -function wrapWithHoc(Component: (props: any, ref: React$Ref<any>) => any) {
111 +function wrapWithHoc(
112 + Component: (props: any, ref: React$RefSetter<any>) => any,
113 +) {
114 function Hoc() {
115 return <Component />;
116 }
packages/react-markup/src/ReactMarkupServer.js
+1 -1
@@ -46,7 +46,7 @@ import {
46 type ReactMarkupNodeList =
47 // This is the intersection of ReactNodeList and ReactClientValue minus
48 // Client/ServerReferences.
49 - | React$Element<React$AbstractComponent<any, any>>
49 + | React$Element<React$ComponentType<any>>
50 | LazyComponent<ReactMarkupNodeList, any>
51 | React$Element<string>
52 | string
packages/react-native-renderer/src/ReactNativeFiberHostComponent.js
+2 -3
@@ -7,9 +7,8 @@
7 * @flow
8 */
9
10 -import type {ElementRef} from 'react';
10 import type {
12 - HostComponent,
11 + HostInstance,
12 MeasureInWindowOnSuccessCallback,
13 MeasureLayoutOnSuccessCallback,
14 MeasureOnSuccessCallback,
@@ -72,7 +71,7 @@ class ReactNativeFiberHostComponent implements INativeMethods {
71 }
72
73 measureLayout(
75 - relativeToNativeNode: number | ElementRef<HostComponent<mixed>>,
74 + relativeToNativeNode: number | HostInstance,
75 onSuccess: MeasureLayoutOnSuccessCallback,
76 onFail?: () => void /* currently unused */,
77 ) {
packages/react-native-renderer/src/ReactNativePublicCompat.js
+2 -2
@@ -32,7 +32,7 @@ import {
32
33 export function findHostInstance_DEPRECATED<TElementType: ElementType>(
34 componentOrHandle: ?(ElementRef<TElementType> | number),
35 -): ?ElementRef<HostComponent<mixed>> {
35 +): ?ElementRef<HostComponent<{...}>> {
36 if (__DEV__) {
37 const owner = currentOwner;
38 if (owner !== null && isRendering && owner.stateNode !== null) {
@@ -225,7 +225,7 @@ export function getNodeFromInternalInstanceHandle(
225 // Should have been PublicInstance from ReactFiberConfigFabric
226 type FabricPublicInstance = mixed;
227 // Should have been PublicInstance from ReactFiberConfigNative
228 -type PaperPublicInstance = HostComponent<mixed>;
228 +type PaperPublicInstance = HostComponent<empty>;
229
230 // Remove this once Paper is no longer supported and DOM Node API are enabled by default in RN.
231 export function isChildPublicInstance(
packages/react-native-renderer/src/ReactNativeTypes.js
+8 -9
@@ -9,12 +9,7 @@
9 * @flow strict
10 */
11
12 -import type {
13 - ElementRef,
14 - ElementType,
15 - MixedElement,
16 - AbstractComponent,
17 -} from 'react';
12 +import type {ElementRef, ElementType, MixedElement} from 'react';
13
14 export type MeasureOnSuccessCallback = (
15 x: number,
@@ -137,7 +132,9 @@ declare const ensureNativeMethodsAreSynced: NativeMethods;
132 (ensureNativeMethodsAreSynced: INativeMethods);
133
134 export type HostInstance = NativeMethods;
140 -export type HostComponent<Config> = AbstractComponent<Config, HostInstance>;
135 +/*::
136 +export type HostComponent<Config: {...}> = component(ref: React$RefSetter<HostInstance>, ...Config);
137 +*/
138
139 type InspectorDataProps = $ReadOnly<{
140 [propName: string]: string,
@@ -208,8 +205,10 @@ export type ReactNativeType = {
205 componentOrHandle: ?(ElementRef<TElementType> | number),
206 ): ?number,
207 isChildPublicInstance(
211 - parent: PublicInstance | HostComponent<mixed>,
212 - child: PublicInstance | HostComponent<mixed>,
208 + // eslint-disable-next-line no-undef
209 + parent: PublicInstance | HostComponent<empty>,
210 + // eslint-disable-next-line no-undef
211 + child: PublicInstance | HostComponent<empty>,
212 ): boolean,
213 dispatchCommand(
214 handle: HostInstance,
packages/react-reconciler/src/ReactTestSelectors.js
+2 -2
@@ -48,7 +48,7 @@ type Type = symbol | number;
48
49 type ComponentSelector = {
50 $$typeof: Type,
51 - value: React$AbstractComponent<empty, mixed>,
51 + value: React$ComponentType<empty>,
52 };
53
54 type HasPseudoClassSelector = {
@@ -79,7 +79,7 @@ type Selector =
79 | TestNameSelector;
80
81 export function createComponentSelector(
82 - component: React$AbstractComponent<empty, mixed>,
82 + component: React$ComponentType<empty>,
83 ): ComponentSelector {
84 return {
85 $$typeof: COMPONENT_TYPE,
packages/react-server/src/ReactFlightServer.js
+1 -1
@@ -297,7 +297,7 @@ type ReactJSONValue =
297 // Serializable values
298 export type ReactClientValue =
299 // Server Elements and Lazy Components are unwrapped on the Server
300 - | React$Element<React$AbstractComponent<any, any>>
300 + | React$Element<React$ComponentType<any>>
301 | LazyComponent<ReactClientValue, any>
302 // References are passed by their value
303 | ClientReference<any>
packages/react/index.development.js
+1 -5
@@ -9,14 +9,10 @@
9
10 // Keep in sync with https://github.com/facebook/flow/blob/main/lib/react.js
11 export type ComponentType<-P> = React$ComponentType<P>;
12 -export type AbstractComponent<
13 - -Config,
14 - +Instance = mixed,
15 -> = React$AbstractComponent<Config, Instance>;
12 +export type AbstractComponent<-Config> = React$AbstractComponent<Config>;
13 export type ElementType = React$ElementType;
14 export type Element<+C> = React$Element<C>;
15 export type Key = React$Key;
19 -export type Ref<C> = React$Ref<C>;
16 export type Node = React$Node;
17 export type Context<T> = React$Context<T>;
18 export type Portal = React$Portal;
packages/react/index.js
+1 -5
@@ -9,15 +9,11 @@
9
10 // Keep in sync with https://github.com/facebook/flow/blob/main/lib/react.js
11 export type ComponentType<-P> = React$ComponentType<P>;
12 -export type AbstractComponent<
13 - -Config,
14 - +Instance = mixed,
15 -> = React$AbstractComponent<Config, Instance>;
12 +export type AbstractComponent<-Config> = React$AbstractComponent<Config>;
13 export type ElementType = React$ElementType;
14 export type Element<+C> = React$Element<C>;
15 export type MixedElement = React$Element<ElementType>;
16 export type Key = React$Key;
20 -export type Ref<C> = React$Ref<C>;
17 export type Node = React$Node;
18 export type Context<T> = React$Context<T>;
19 export type Portal = React$Portal;
packages/react/src/ReactForwardRef.js
+4 -1
@@ -10,7 +10,10 @@
10 import {REACT_FORWARD_REF_TYPE, REACT_MEMO_TYPE} from 'shared/ReactSymbols';
11
12 export function forwardRef<Props, ElementType: React$ElementType>(
13 - render: (props: Props, ref: React$Ref<ElementType>) => React$Node,
13 + render: (
14 + props: Props,
15 + ref: React$RefSetter<React$ElementRef<ElementType>>,
16 + ) => React$Node,
17 ) {
18 if (__DEV__) {
19 if (render != null && render.$$typeof === REACT_MEMO_TYPE) {