Skip to content

Commit

Permalink
[react] React.forwardRef
Browse files Browse the repository at this point in the history
Summary:
With AbstractComponent done, we can finally write out the type for forwardRef. For docs, check here: https://reactjs.org/docs/forwarding-refs.html

Notable limitations:
The Component returned from forwardRef has no defaultProps. Since they are in an invariant position, you won't be able to assign them defaultProps later. This is fine for most use cases.

If we do need to support defaultProps on forwardRef components, we would need a function like:
```
withDefaultProps<Config, DefaultProps, Instance>(
   x: React.AbstractComponent<Config, void, Instance>,
   defaultProps: DefaultProps,
): React.AbstractComponent<React.Config<Config, DefaultProps>, DefaultProps, Instance>;
```

If there is demand for it, I will look more into creating a library with flow types that accomplishes this.

----

Special thanks to Sam Goldman for all the reviewing and discussions it took to get this done!

Fixes: #6103

Reviewed By: samwgoldman

Differential Revision: D13270565

fbshipit-source-id: e99718a0ca5942eb825d13dbcd3acf3f38b2802f
  • Loading branch information
jbrown215 authored and facebook-github-bot committed Dec 4, 2018
1 parent 77f2c40 commit 9a3377a
Show file tree
Hide file tree
Showing 11 changed files with 697 additions and 581 deletions.
8 changes: 8 additions & 0 deletions lib/react.js
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,13 @@ declare module react {
toArray<T>(children: ChildrenArray<T>): Array<$NonMaybeType<T>>;
};

declare export function forwardRef<Config, Instance>(
render: (
props: Config,
ref: {current: null | Instance} | ((null | Instance) => mixed),
) => React$Node,
): React$AbstractComponent<Config, void, Instance>;

declare export function memo<P>(
component: React$StatelessFunctionalComponent<P>,
equal?: (P, P) => boolean,
Expand Down Expand Up @@ -355,6 +362,7 @@ declare module react {
+cloneElement: typeof cloneElement,
+createFactory: typeof createFactory,
+createRef: typeof createRef,
+forwardRef: typeof forwardRef,
+isValidElement: typeof isValidElement,
+Component: typeof Component,
+PureComponent: typeof PureComponent,
Expand Down
8 changes: 4 additions & 4 deletions tests/getters_and_setters/getters_and_setters.exp
Original file line number Diff line number Diff line change
Expand Up @@ -465,8 +465,8 @@ References:
react.js:17:13
17| (<Example a="bad" />); // error: number ~> string
^^^^^ [1]
<BUILTINS>/react.js:414:36
414| number: React$PropType$Primitive<number>;
<BUILTINS>/react.js:422:36
422| number: React$PropType$Primitive<number>;
^^^^^^ [2]


Expand All @@ -482,8 +482,8 @@ References:
react.js:18:20
18| (<Example a={0} c={0} />); // error: number ~> string
^ [1]
<BUILTINS>/react.js:416:36
416| string: React$PropType$Primitive<string>;
<BUILTINS>/react.js:424:36
424| string: React$PropType$Primitive<string>;
^^^^^^ [2]


Expand Down
46 changes: 23 additions & 23 deletions tests/new_react/new_react.exp
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,8 @@ Cannot assign `this.props.x` to `_` because number [1] is incompatible with stri
^^^^^^^^^^^^

References:
<BUILTINS>/react.js:414:36
414| number: React$PropType$Primitive<number>;
<BUILTINS>/react.js:422:36
422| number: React$PropType$Primitive<number>;
^^^^^^ [1]
classes.js:57:12
57| var _: string = this.props.x;
Expand Down Expand Up @@ -402,8 +402,8 @@ Cannot assign `this.props.z` to `qux` because:
^^^^^^^^^^^^

References:
<BUILTINS>/react.js:414:36
414| number: React$PropType$Primitive<number>;
<BUILTINS>/react.js:422:36
422| number: React$PropType$Primitive<number>;
^^^^^^ [1]
new_react.js:19:18
19| var qux: string = this.props.z;
Expand All @@ -419,8 +419,8 @@ Cannot assign `this.props.x` to `w` because string [1] is incompatible with numb
^^^^^^^^^^^^

References:
<BUILTINS>/react.js:416:36
416| string: React$PropType$Primitive<string>;
<BUILTINS>/react.js:424:36
424| string: React$PropType$Primitive<string>;
^^^^^^ [1]
new_react.js:20:15
20| var w:number = this.props.x;
Expand Down Expand Up @@ -453,8 +453,8 @@ References:
new_react.js:29:23
29| var element = <C x = {0}/>;
^ [1]
<BUILTINS>/react.js:416:36
416| string: React$PropType$Primitive<string>;
<BUILTINS>/react.js:424:36
424| string: React$PropType$Primitive<string>;
^^^^^^ [2]


Expand Down Expand Up @@ -559,8 +559,8 @@ Cannot assign `this.props.x` to `a` because:
^^^^^^^^^^^^

References:
<BUILTINS>/react.js:416:36
416| string: React$PropType$Primitive<string>;
<BUILTINS>/react.js:424:36
424| string: React$PropType$Primitive<string>;
^^^^^^ [1]
props.js:14:16
14| var a: number = this.props.x; // error
Expand Down Expand Up @@ -596,8 +596,8 @@ Cannot assign `this.props.z` to `c` because:
^^^^^^^^^^^^

References:
<BUILTINS>/react.js:414:36
414| number: React$PropType$Primitive<number>;
<BUILTINS>/react.js:422:36
422| number: React$PropType$Primitive<number>;
^^^^^^ [1]
props.js:16:16
16| var c: string = this.props.z; // error
Expand All @@ -618,14 +618,14 @@ References:
props.js:20:29
20| var element = <TestProps x={false} y={false} z={false} />; // 3 errors
^^^^^ [1]
<BUILTINS>/react.js:416:36
416| string: React$PropType$Primitive<string>;
<BUILTINS>/react.js:424:36
424| string: React$PropType$Primitive<string>;
^^^^^^ [2]
props.js:20:49
20| var element = <TestProps x={false} y={false} z={false} />; // 3 errors
^^^^^ [3]
<BUILTINS>/react.js:414:36
414| number: React$PropType$Primitive<number>;
<BUILTINS>/react.js:422:36
422| number: React$PropType$Primitive<number>;
^^^^^^ [4]


Expand Down Expand Up @@ -682,8 +682,8 @@ References:
props2.js:9:41
9| getInitialState: function(): { bar: number } {
^^^^^^ [1]
<BUILTINS>/react.js:416:36
416| string: React$PropType$Primitive<string>;
<BUILTINS>/react.js:424:36
424| string: React$PropType$Primitive<string>;
^^^^^^ [2]
props2.js:15:42
15| return <C {...this.state} foo = {0} />;
Expand Down Expand Up @@ -714,12 +714,12 @@ Cannot get `React.PropTypes.string.inRequired` because property `inRequired` is
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

References:
<BUILTINS>/react.js:390:39
<BUILTINS>/react.js:398:39
v
390| type ReactPropsChainableTypeChecker = {
391| isRequired: ReactPropsCheckType;
392| (props: any, propName: string, componentName: string, href?: string): ?Error;
393| };
398| type ReactPropsChainableTypeChecker = {
399| isRequired: ReactPropsCheckType;
400| (props: any, propName: string, componentName: string, href?: string): ?Error;
401| };
^ [1]


Expand Down
Loading

0 comments on commit 9a3377a

Please sign in to comment.