From a80397e5960778ff8bd818837c752b8dcb9e6cc6 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 27 Nov 2018 14:30:27 -0800 Subject: [PATCH] Make React.Suspense "fallback" prop optional (and add nested Suspense test cases) --- lib/react.js | 2 +- tests/react_16_6/Suspense.js | 26 +++++++++----- tests/react_16_6/react_16_6.exp | 35 +++++-------------- tests/type-at-pos_react/type-at-pos_react.exp | 2 +- 4 files changed, 27 insertions(+), 38 deletions(-) diff --git a/lib/react.js b/lib/react.js index 5b7dccaa3e7..522bbe5a572 100644 --- a/lib/react.js +++ b/lib/react.js @@ -252,7 +252,7 @@ declare module react { declare export var Suspense: React$ComponentType<{ children?: ?React$Node, - fallback: React$Node, + fallback?: React$Node, maxDuration?: number }>; // 16.6+ diff --git a/tests/react_16_6/Suspense.js b/tests/react_16_6/Suspense.js index d3da6e059da..3e226fa50e3 100644 --- a/tests/react_16_6/Suspense.js +++ b/tests/react_16_6/Suspense.js @@ -8,10 +8,6 @@ function Loading() { return
Loading...
; } -{ - // Error: fallback is missing in props -} - { } maxDuration="abc" /> // Error: string is incompatible with number } @@ -24,18 +20,30 @@ function Loading() { } /> } +{ + } maxDuration={1000} /> +} + +{ + } maxDuration={1000}> +
Hello
+
+} + { }> - + } { - } maxDuration={1000} /> + }> + + } { - } maxDuration={1000}> - + }> + -} \ No newline at end of file +} diff --git a/tests/react_16_6/react_16_6.exp b/tests/react_16_6/react_16_6.exp index cc7bfffb75d..86d1347ce0d 100644 --- a/tests/react_16_6/react_16_6.exp +++ b/tests/react_16_6/react_16_6.exp @@ -1,48 +1,29 @@ Error ------------------------------------------------------------------------------------------------- Suspense.js:12:3 -Cannot create `Suspense` element because property `fallback` is missing in props [1] but exists in object type [2]. - - Suspense.js:12:3 - 12| // Error: fallback is missing in props - ^^^^^^^^^^^^ [1] - -References: - /react.js:253:52 - v - 253| declare export var Suspense: React$ComponentType<{ - 254| children?: ?React$Node, - 255| fallback: React$Node, - 256| maxDuration?: number - 257| }>; // 16.6+ - ^ [2] - - -Error ------------------------------------------------------------------------------------------------- Suspense.js:16:3 - Cannot create `Suspense` element because string [1] is incompatible with number [2] in property `maxDuration`. - Suspense.js:16:3 - 16| } maxDuration="abc" /> // Error: string is incompatible with number + Suspense.js:12:3 + 12| } maxDuration="abc" /> // Error: string is incompatible with number ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ References: - Suspense.js:16:48 - 16| } maxDuration="abc" /> // Error: string is incompatible with number + Suspense.js:12:48 + 12| } maxDuration="abc" /> // Error: string is incompatible with number ^^^^^ [1] /react.js:256:19 256| maxDuration?: number ^^^^^^ [2] -Error ------------------------------------------------------------------------------------------------- Suspense.js:20:3 +Error ------------------------------------------------------------------------------------------------- Suspense.js:16:3 Cannot create `Suspense` element because in property `fallback`: - Either inexact function [1] is incompatible with exact `React.Element` [2]. - Or function [1] is incompatible with `React.Portal` [3]. - Or property `@@iterator` is missing in function [1] but exists in `$Iterable` [4]. - Suspense.js:20:3 - 20| // Error: function is incompatible with exact React.Element + Suspense.js:16:3 + 16| // Error: function is incompatible with exact React.Element ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ References: @@ -241,7 +222,7 @@ References: -Found 15 errors +Found 14 errors Only showing the most relevant union/intersection branches. To see all branches, re-run Flow with --show-all-branches diff --git a/tests/type-at-pos_react/type-at-pos_react.exp b/tests/type-at-pos_react/type-at-pos_react.exp index 127f4b9a7f5..9318368e350 100644 --- a/tests/type-at-pos_react/type-at-pos_react.exp +++ b/tests/type-at-pos_react/type-at-pos_react.exp @@ -1,5 +1,5 @@ react_component.js:3:9 = { - "type":"{|+Children: {+count: (children: ChildrenArray) => number, +forEach: (children: ChildrenArray, fn: (child: T, index: number) => mixed, thisArg?: mixed) => void, +map: (children: ChildrenArray, fn: (child: $NonMaybeType, index: number) => U, thisArg?: mixed) => Array<$NonMaybeType>, +only: (children: ChildrenArray) => $NonMaybeType, +toArray: (children: ChildrenArray) => Array<$NonMaybeType>}, +ChildrenArray: type ChildrenArray<+T> = $ReadOnlyArray> | T, +Component: class React$Component, +ComponentType: type ComponentType

= React$ComponentType

, +ConcurrentMode: ({children: ?React$Node}) => React$Node, +Context: type Context = React$Context, +DOM: any, +Element: type Element<+C> = React$Element, +ElementConfig: type ElementConfig = React$ElementConfig, +ElementProps: type ElementProps = React$ElementProps, +ElementRef: type ElementRef = React$ElementRef, +ElementType: type ElementType = React$ElementType, +Fragment: ({children: ?React$Node}) => React$Node, +Key: type Key = React$Key, +Node: type Node = React$Node, +Portal: type Portal = React$Portal, +PropTypes: ReactPropTypes, +PureComponent: class React$PureComponent, +Ref: type Ref = React$Ref, +StatelessFunctionalComponent: type StatelessFunctionalComponent

= React$StatelessFunctionalComponent

, +StrictMode: ({children: ?React$Node}) => React$Node, +Suspense: React$ComponentType<{children?: ?React$Node, fallback: React$Node, maxDuration?: number}>, +checkPropTypes: (propTypes: $Subtype<{[_: $Keys]: ReactPropsCheckType}>, values: V, location: string, componentName: string, getStack: ?(() => ?string)) => void, +cloneElement: React$CloneElement, +createClass: React$CreateClass, +createContext: (defaultValue: T, calculateChangedBits: ?((a: T, b: T) => number)) => React$Context, +createElement: React$CreateElement, +createFactory: (type: ElementType) => React$ElementFactory, +createRef: () => {current: (null | T)}, +default: {|+Children: {+count: (children: ChildrenArray) => number, +forEach: (children: ChildrenArray, fn: (child: T, index: number) => mixed, thisArg?: mixed) => void, +map: (children: ChildrenArray, fn: (child: $NonMaybeType, index: number) => U, thisArg?: mixed) => Array<$NonMaybeType>, +only: (children: ChildrenArray) => $NonMaybeType, +toArray: (children: ChildrenArray) => Array<$NonMaybeType>}, +Component: class React$Component, +ConcurrentMode: ({children: ?React$Node}) => React$Node, +DOM: any, +Fragment: ({children: ?React$Node}) => React$Node, +PropTypes: ReactPropTypes, +PureComponent: class React$PureComponent, +StrictMode: ({children: ?React$Node}) => React$Node, +Suspense: React$ComponentType<{children?: ?React$Node, fallback: React$Node, maxDuration?: number}>, +checkPropTypes: (propTypes: $Subtype<{[_: $Keys]: ReactPropsCheckType}>, values: V, location: string, componentName: string, getStack: ?(() => ?string)) => void, +cloneElement: React$CloneElement, +createClass: React$CreateClass, +createContext: (defaultValue: T, calculateChangedBits: ?((a: T, b: T) => number)) => React$Context, +createElement: React$CreateElement, +createFactory: (type: ElementType) => React$ElementFactory, +createRef: () => {current: (null | T)}, +isValidElement: (element: any) => boolean, +lazy:

(component: () => React$ComponentType

) => React$ComponentType

, +memo:

(component: React$StatelessFunctionalComponent

, equal?: (P, P) => boolean) => React$StatelessFunctionalComponent

, +useCallback: (callback: () => (T | void), inputs: ?$ReadOnlyArray) => T, +useContext: (context: React$Context, observedBits: (void | number | boolean)) => T, +useEffect: (create: () => MaybeCleanUpFn, inputs: ?$ReadOnlyArray) => void, +useImperativeMethods: (ref: ?({current: (T | null)} | ((inst: (T | null)) => mixed)), create: () => T, inputs: ?$ReadOnlyArray) => void, +useLayoutEffect: (create: () => MaybeCleanUpFn, inputs: ?$ReadOnlyArray) => void, +useMemo: (create: () => T, inputs: ?$ReadOnlyArray) => T, +useReducer: (reducer: (S, A) => S, initialState: S, initialAction: ?A) => [S, (A) => void], +useRef: (initialValue: ?T) => {current: (T | null)}, +useState: (initialState: ((() => S) | S)) => [S, ((((S) => S) | S)) => void], +version: string|}, +isValidElement: (element: any) => boolean, +lazy:

(component: () => React$ComponentType

) => React$ComponentType

, +memo:

(component: React$StatelessFunctionalComponent

, equal?: (P, P) => boolean) => React$StatelessFunctionalComponent

, +useCallback: (callback: () => (T | void), inputs: ?$ReadOnlyArray) => T, +useContext: (context: React$Context, observedBits: (void | number | boolean)) => T, +useEffect: (create: () => MaybeCleanUpFn, inputs: ?$ReadOnlyArray) => void, +useImperativeMethods: (ref: ?({current: (T | null)} | ((inst: (T | null)) => mixed)), create: () => T, inputs: ?$ReadOnlyArray) => void, +useLayoutEffect: (create: () => MaybeCleanUpFn, inputs: ?$ReadOnlyArray) => void, +useMemo: (create: () => T, inputs: ?$ReadOnlyArray) => T, +useReducer: (reducer: (S, A) => S, initialState: S, initialAction: ?A) => [S, (A) => void], +useRef: (initialValue: ?T) => {current: (T | null)}, +useState: (initialState: ((() => S) | S)) => [S, ((((S) => S) | S)) => void], +version: string|}", + "type":"{|+Children: {+count: (children: ChildrenArray) => number, +forEach: (children: ChildrenArray, fn: (child: T, index: number) => mixed, thisArg?: mixed) => void, +map: (children: ChildrenArray, fn: (child: $NonMaybeType, index: number) => U, thisArg?: mixed) => Array<$NonMaybeType>, +only: (children: ChildrenArray) => $NonMaybeType, +toArray: (children: ChildrenArray) => Array<$NonMaybeType>}, +ChildrenArray: type ChildrenArray<+T> = $ReadOnlyArray> | T, +Component: class React$Component, +ComponentType: type ComponentType

= React$ComponentType

, +ConcurrentMode: ({children: ?React$Node}) => React$Node, +Context: type Context = React$Context, +DOM: any, +Element: type Element<+C> = React$Element, +ElementConfig: type ElementConfig = React$ElementConfig, +ElementProps: type ElementProps = React$ElementProps, +ElementRef: type ElementRef = React$ElementRef, +ElementType: type ElementType = React$ElementType, +Fragment: ({children: ?React$Node}) => React$Node, +Key: type Key = React$Key, +Node: type Node = React$Node, +Portal: type Portal = React$Portal, +PropTypes: ReactPropTypes, +PureComponent: class React$PureComponent, +Ref: type Ref = React$Ref, +StatelessFunctionalComponent: type StatelessFunctionalComponent

= React$StatelessFunctionalComponent

, +StrictMode: ({children: ?React$Node}) => React$Node, +Suspense: React$ComponentType<{children?: ?React$Node, fallback?: React$Node, maxDuration?: number}>, +checkPropTypes: (propTypes: $Subtype<{[_: $Keys]: ReactPropsCheckType}>, values: V, location: string, componentName: string, getStack: ?(() => ?string)) => void, +cloneElement: React$CloneElement, +createClass: React$CreateClass, +createContext: (defaultValue: T, calculateChangedBits: ?((a: T, b: T) => number)) => React$Context, +createElement: React$CreateElement, +createFactory: (type: ElementType) => React$ElementFactory, +createRef: () => {current: (null | T)}, +default: {|+Children: {+count: (children: ChildrenArray) => number, +forEach: (children: ChildrenArray, fn: (child: T, index: number) => mixed, thisArg?: mixed) => void, +map: (children: ChildrenArray, fn: (child: $NonMaybeType, index: number) => U, thisArg?: mixed) => Array<$NonMaybeType>, +only: (children: ChildrenArray) => $NonMaybeType, +toArray: (children: ChildrenArray) => Array<$NonMaybeType>}, +Component: class React$Component, +ConcurrentMode: ({children: ?React$Node}) => React$Node, +DOM: any, +Fragment: ({children: ?React$Node}) => React$Node, +PropTypes: ReactPropTypes, +PureComponent: class React$PureComponent, +StrictMode: ({children: ?React$Node}) => React$Node, +Suspense: React$ComponentType<{children?: ?React$Node, fallback?: React$Node, maxDuration?: number}>, +checkPropTypes: (propTypes: $Subtype<{[_: $Keys]: ReactPropsCheckType}>, values: V, location: string, componentName: string, getStack: ?(() => ?string)) => void, +cloneElement: React$CloneElement, +createClass: React$CreateClass, +createContext: (defaultValue: T, calculateChangedBits: ?((a: T, b: T) => number)) => React$Context, +createElement: React$CreateElement, +createFactory: (type: ElementType) => React$ElementFactory, +createRef: () => {current: (null | T)}, +isValidElement: (element: any) => boolean, +lazy:

(component: () => React$ComponentType

) => React$ComponentType

, +memo:

(component: React$StatelessFunctionalComponent

, equal?: (P, P) => boolean) => React$StatelessFunctionalComponent

, +useCallback: (callback: () => (T | void), inputs: ?$ReadOnlyArray) => T, +useContext: (context: React$Context, observedBits: (void | number | boolean)) => T, +useEffect: (create: () => MaybeCleanUpFn, inputs: ?$ReadOnlyArray) => void, +useImperativeMethods: (ref: ?({current: (T | null)} | ((inst: (T | null)) => mixed)), create: () => T, inputs: ?$ReadOnlyArray) => void, +useLayoutEffect: (create: () => MaybeCleanUpFn, inputs: ?$ReadOnlyArray) => void, +useMemo: (create: () => T, inputs: ?$ReadOnlyArray) => T, +useReducer: (reducer: (S, A) => S, initialState: S, initialAction: ?A) => [S, (A) => void], +useRef: (initialValue: ?T) => {current: (T | null)}, +useState: (initialState: ((() => S) | S)) => [S, ((((S) => S) | S)) => void], +version: string|}, +isValidElement: (element: any) => boolean, +lazy:

(component: () => React$ComponentType

) => React$ComponentType

, +memo:

(component: React$StatelessFunctionalComponent

, equal?: (P, P) => boolean) => React$StatelessFunctionalComponent

, +useCallback: (callback: () => (T | void), inputs: ?$ReadOnlyArray) => T, +useContext: (context: React$Context, observedBits: (void | number | boolean)) => T, +useEffect: (create: () => MaybeCleanUpFn, inputs: ?$ReadOnlyArray) => void, +useImperativeMethods: (ref: ?({current: (T | null)} | ((inst: (T | null)) => mixed)), create: () => T, inputs: ?$ReadOnlyArray) => void, +useLayoutEffect: (create: () => MaybeCleanUpFn, inputs: ?$ReadOnlyArray) => void, +useMemo: (create: () => T, inputs: ?$ReadOnlyArray) => T, +useReducer: (reducer: (S, A) => S, initialState: S, initialAction: ?A) => [S, (A) => void], +useRef: (initialValue: ?T) => {current: (T | null)}, +useState: (initialState: ((() => S) | S)) => [S, ((((S) => S) | S)) => void], +version: string|}", "reasons":[], "loc":{ "source":"react_component.js",