Skip to content

Commit

Permalink
[flow] Eliminate usage of more than 1-arg React.AbstractComponent i…
Browse files Browse the repository at this point in the history
…n 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
  • Loading branch information
SamChou19815 authored Oct 21, 2024
1 parent 69d4b80 commit 45804af
Show file tree
Hide file tree
Showing 15 changed files with 36 additions and 38 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,7 @@ module.exports = {
React$Node: 'readonly',
React$Portal: 'readonly',
React$Ref: 'readonly',
React$RefSetter: 'readonly',
ReadableStreamController: 'readonly',
ReadableStreamReader: 'readonly',
RequestInfo: 'readonly',
Expand Down
2 changes: 1 addition & 1 deletion packages/react-devtools-inline/src/frontend.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export function initialize(
bridge?: FrontendBridge,
store?: Store,
} = {},
): React.AbstractComponent<Props, mixed> {
): React.ComponentType<Props> {
if (bridge == null) {
bridge = createBridge(contentWindow);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @flow
*/

import type {Node as ReactNode, AbstractComponent, ElementRef} from 'react';
import type {Node as ReactNode} from 'react';

export type ContextMenuItem = {
onClick: () => void,
Expand All @@ -25,5 +25,7 @@ export type ContextMenuHandle = {
hide(): void,
};

export type ContextMenuComponent = AbstractComponent<{}, ContextMenuHandle>;
export type ContextMenuRef = {current: ElementRef<ContextMenuComponent> | null};
/*::
export type ContextMenuComponent = component(ref: React$RefSetter<ContextMenuHandle>);
*/
export type ContextMenuRef = {current: ContextMenuHandle | null};
Original file line number Diff line number Diff line change
Expand Up @@ -246,4 +246,4 @@ function setResizeCSSVariable(
}
}

export default (portaledContent(Components): React$AbstractComponent<{}>);
export default (portaledContent(Components): React$ComponentType<{}>);
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import ThemeProvider from './ThemeProvider';
export type Props = {portalContainer?: Element, ...};

export default function portaledContent(
Component: React$AbstractComponent<any>,
): React$AbstractComponent<any> {
Component: React$ComponentType<any>,
): React$ComponentType<any> {
return function PortaledContent({portalContainer, ...rest}: Props) {
const store = useContext(StoreContext);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ function useDeepHookF() {
const ContextA = createContext('A');
const ContextB = createContext('B');

function FunctionWithHooks(props: any, ref: React$Ref<any>) {
function FunctionWithHooks(props: any, ref: React$RefSetter<any>) {
const [count, updateCount] = useState(0);
// eslint-disable-next-line no-unused-vars
const contextValueA = useContext(ContextA);
Expand Down Expand Up @@ -108,7 +108,9 @@ function FunctionWithHooks(props: any, ref: React$Ref<any>) {
const MemoWithHooks = memo(FunctionWithHooks);
const ForwardRefWithHooks = forwardRef(FunctionWithHooks);

function wrapWithHoc(Component: (props: any, ref: React$Ref<any>) => any) {
function wrapWithHoc(
Component: (props: any, ref: React$RefSetter<any>) => any,
) {
function Hoc() {
return <Component />;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/react-markup/src/ReactMarkupServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ import {
type ReactMarkupNodeList =
// This is the intersection of ReactNodeList and ReactClientValue minus
// Client/ServerReferences.
| React$Element<React$AbstractComponent<any, any>>
| React$Element<React$ComponentType<any>>
| LazyComponent<ReactMarkupNodeList, any>
| React$Element<string>
| string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
* @flow
*/

import type {ElementRef} from 'react';
import type {
HostComponent,
HostInstance,
MeasureInWindowOnSuccessCallback,
MeasureLayoutOnSuccessCallback,
MeasureOnSuccessCallback,
Expand Down Expand Up @@ -72,7 +71,7 @@ class ReactNativeFiberHostComponent implements INativeMethods {
}

measureLayout(
relativeToNativeNode: number | ElementRef<HostComponent<mixed>>,
relativeToNativeNode: number | HostInstance,
onSuccess: MeasureLayoutOnSuccessCallback,
onFail?: () => void /* currently unused */,
) {
Expand Down
4 changes: 2 additions & 2 deletions packages/react-native-renderer/src/ReactNativePublicCompat.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {

export function findHostInstance_DEPRECATED<TElementType: ElementType>(
componentOrHandle: ?(ElementRef<TElementType> | number),
): ?ElementRef<HostComponent<mixed>> {
): ?ElementRef<HostComponent<{...}>> {
if (__DEV__) {
const owner = currentOwner;
if (owner !== null && isRendering && owner.stateNode !== null) {
Expand Down Expand Up @@ -225,7 +225,7 @@ export function getNodeFromInternalInstanceHandle(
// Should have been PublicInstance from ReactFiberConfigFabric
type FabricPublicInstance = mixed;
// Should have been PublicInstance from ReactFiberConfigNative
type PaperPublicInstance = HostComponent<mixed>;
type PaperPublicInstance = HostComponent<empty>;

// Remove this once Paper is no longer supported and DOM Node API are enabled by default in RN.
export function isChildPublicInstance(
Expand Down
17 changes: 8 additions & 9 deletions packages/react-native-renderer/src/ReactNativeTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,7 @@
* @flow strict
*/

import type {
ElementRef,
ElementType,
MixedElement,
AbstractComponent,
} from 'react';
import type {ElementRef, ElementType, MixedElement} from 'react';

export type MeasureOnSuccessCallback = (
x: number,
Expand Down Expand Up @@ -137,7 +132,9 @@ declare const ensureNativeMethodsAreSynced: NativeMethods;
(ensureNativeMethodsAreSynced: INativeMethods);

export type HostInstance = NativeMethods;
export type HostComponent<Config> = AbstractComponent<Config, HostInstance>;
/*::
export type HostComponent<Config: {...}> = component(ref: React$RefSetter<HostInstance>, ...Config);
*/

type InspectorDataProps = $ReadOnly<{
[propName: string]: string,
Expand Down Expand Up @@ -208,8 +205,10 @@ export type ReactNativeType = {
componentOrHandle: ?(ElementRef<TElementType> | number),
): ?number,
isChildPublicInstance(
parent: PublicInstance | HostComponent<mixed>,
child: PublicInstance | HostComponent<mixed>,
// eslint-disable-next-line no-undef
parent: PublicInstance | HostComponent<empty>,
// eslint-disable-next-line no-undef
child: PublicInstance | HostComponent<empty>,
): boolean,
dispatchCommand(
handle: HostInstance,
Expand Down
4 changes: 2 additions & 2 deletions packages/react-reconciler/src/ReactTestSelectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ type Type = symbol | number;

type ComponentSelector = {
$$typeof: Type,
value: React$AbstractComponent<empty, mixed>,
value: React$ComponentType<empty>,
};

type HasPseudoClassSelector = {
Expand Down Expand Up @@ -79,7 +79,7 @@ type Selector =
| TestNameSelector;

export function createComponentSelector(
component: React$AbstractComponent<empty, mixed>,
component: React$ComponentType<empty>,
): ComponentSelector {
return {
$$typeof: COMPONENT_TYPE,
Expand Down
2 changes: 1 addition & 1 deletion packages/react-server/src/ReactFlightServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ type ReactJSONValue =
// Serializable values
export type ReactClientValue =
// Server Elements and Lazy Components are unwrapped on the Server
| React$Element<React$AbstractComponent<any, any>>
| React$Element<React$ComponentType<any>>
| LazyComponent<ReactClientValue, any>
// References are passed by their value
| ClientReference<any>
Expand Down
6 changes: 1 addition & 5 deletions packages/react/index.development.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,10 @@

// Keep in sync with https://github.com/facebook/flow/blob/main/lib/react.js
export type ComponentType<-P> = React$ComponentType<P>;
export type AbstractComponent<
-Config,
+Instance = mixed,
> = React$AbstractComponent<Config, Instance>;
export type AbstractComponent<-Config> = React$AbstractComponent<Config>;
export type ElementType = React$ElementType;
export type Element<+C> = React$Element<C>;
export type Key = React$Key;
export type Ref<C> = React$Ref<C>;
export type Node = React$Node;
export type Context<T> = React$Context<T>;
export type Portal = React$Portal;
Expand Down
6 changes: 1 addition & 5 deletions packages/react/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,11 @@

// Keep in sync with https://github.com/facebook/flow/blob/main/lib/react.js
export type ComponentType<-P> = React$ComponentType<P>;
export type AbstractComponent<
-Config,
+Instance = mixed,
> = React$AbstractComponent<Config, Instance>;
export type AbstractComponent<-Config> = React$AbstractComponent<Config>;
export type ElementType = React$ElementType;
export type Element<+C> = React$Element<C>;
export type MixedElement = React$Element<ElementType>;
export type Key = React$Key;
export type Ref<C> = React$Ref<C>;
export type Node = React$Node;
export type Context<T> = React$Context<T>;
export type Portal = React$Portal;
Expand Down
5 changes: 4 additions & 1 deletion packages/react/src/ReactForwardRef.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
import {REACT_FORWARD_REF_TYPE, REACT_MEMO_TYPE} from 'shared/ReactSymbols';

export function forwardRef<Props, ElementType: React$ElementType>(
render: (props: Props, ref: React$Ref<ElementType>) => React$Node,
render: (
props: Props,
ref: React$RefSetter<React$ElementRef<ElementType>>,
) => React$Node,
) {
if (__DEV__) {
if (render != null && render.$$typeof === REACT_MEMO_TYPE) {
Expand Down

0 comments on commit 45804af

Please sign in to comment.