react-relay 14.0.0 → 15.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/ReactRelayContainerUtils.js.flow +1 -2
  2. package/ReactRelayContext.js +1 -1
  3. package/ReactRelayContext.js.flow +1 -2
  4. package/ReactRelayFragmentContainer.js.flow +6 -4
  5. package/ReactRelayFragmentMockRenderer.js.flow +1 -2
  6. package/ReactRelayLocalQueryRenderer.js.flow +5 -5
  7. package/ReactRelayPaginationContainer.js.flow +21 -14
  8. package/ReactRelayQueryFetcher.js.flow +28 -16
  9. package/ReactRelayQueryRenderer.js.flow +42 -13
  10. package/ReactRelayQueryRendererContext.js.flow +2 -3
  11. package/ReactRelayRefetchContainer.js.flow +9 -9
  12. package/ReactRelayTestMocker.js.flow +3 -3
  13. package/ReactRelayTypes.js.flow +7 -8
  14. package/RelayContext.js.flow +1 -2
  15. package/__flowtests__/ReactRelayFragmentContainer-flowtest.js.flow +4 -5
  16. package/__flowtests__/ReactRelayPaginationContainer-flowtest.js.flow +4 -5
  17. package/__flowtests__/ReactRelayRefetchContainer-flowtest.js.flow +4 -5
  18. package/__flowtests__/RelayModern-flowtest.js.flow +3 -4
  19. package/__flowtests__/RelayModernFlowtest_badref.graphql.js.flow +3 -4
  20. package/__flowtests__/RelayModernFlowtest_notref.graphql.js.flow +3 -4
  21. package/__flowtests__/RelayModernFlowtest_user.graphql.js.flow +3 -4
  22. package/__flowtests__/RelayModernFlowtest_users.graphql.js.flow +3 -4
  23. package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer.graphql.js.flow +3 -1
  24. package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer2.graphql.js.flow +3 -1
  25. package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtestQuery.graphql.js.flow +4 -2
  26. package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtest_viewer.graphql.js.flow +3 -1
  27. package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtestQuery.graphql.js.flow +4 -2
  28. package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtest_viewer.graphql.js.flow +3 -1
  29. package/__flowtests__/__generated__/RelayModernFlowtest_badref.graphql.js.flow +4 -2
  30. package/__flowtests__/__generated__/RelayModernFlowtest_notref.graphql.js.flow +4 -2
  31. package/__flowtests__/__generated__/RelayModernFlowtest_user.graphql.js.flow +3 -1
  32. package/__flowtests__/__generated__/RelayModernFlowtest_users.graphql.js.flow +3 -1
  33. package/assertFragmentMap.js.flow +1 -2
  34. package/buildReactRelayContainer.js.flow +7 -7
  35. package/getRootVariablesForFragments.js.flow +1 -3
  36. package/hooks.js +1 -1
  37. package/hooks.js.flow +4 -2
  38. package/index.js +1 -1
  39. package/index.js.flow +6 -2
  40. package/isRelayEnvironment.js.flow +1 -2
  41. package/jest-react/enqueueTask.js.flow +1 -1
  42. package/jest-react/index.js.flow +1 -1
  43. package/jest-react/internalAct.js.flow +1 -1
  44. package/legacy.js +1 -1
  45. package/legacy.js.flow +1 -2
  46. package/lib/ReactRelayContainerUtils.js +2 -3
  47. package/lib/ReactRelayContext.js +3 -4
  48. package/lib/ReactRelayFragmentContainer.js +47 -73
  49. package/lib/ReactRelayFragmentMockRenderer.js +2 -4
  50. package/lib/ReactRelayLocalQueryRenderer.js +18 -31
  51. package/lib/ReactRelayPaginationContainer.js +74 -164
  52. package/lib/ReactRelayQueryFetcher.js +49 -76
  53. package/lib/ReactRelayQueryRenderer.js +63 -84
  54. package/lib/ReactRelayQueryRendererContext.js +2 -2
  55. package/lib/ReactRelayRefetchContainer.js +58 -108
  56. package/lib/ReactRelayTestMocker.js +33 -68
  57. package/lib/ReactRelayTypes.js +2 -1
  58. package/lib/RelayContext.js +4 -7
  59. package/lib/assertFragmentMap.js +3 -5
  60. package/lib/buildReactRelayContainer.js +11 -27
  61. package/lib/getRootVariablesForFragments.js +6 -10
  62. package/lib/hooks.js +5 -18
  63. package/lib/index.js +7 -24
  64. package/lib/isRelayEnvironment.js +5 -4
  65. package/lib/jest-react/enqueueTask.js +5 -9
  66. package/lib/jest-react/index.js +0 -1
  67. package/lib/jest-react/internalAct.js +9 -20
  68. package/lib/legacy.js +2 -8
  69. package/lib/multi-actor/ActorChange.js +2 -5
  70. package/lib/multi-actor/index.js +2 -1
  71. package/lib/multi-actor/useRelayActorEnvironment.js +4 -8
  72. package/lib/relay-hooks/EntryPointContainer.react.js +9 -15
  73. package/lib/relay-hooks/EntryPointTypes.flow.js +5 -3
  74. package/lib/relay-hooks/FragmentResource.js +109 -203
  75. package/lib/relay-hooks/HooksImplementation.js +3 -6
  76. package/lib/relay-hooks/InternalLogger.js +2 -3
  77. package/lib/relay-hooks/LRUCache.js +2 -20
  78. package/lib/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js +33 -54
  79. package/lib/relay-hooks/MatchContainer.js +15 -24
  80. package/lib/relay-hooks/ProfilerContext.js +3 -3
  81. package/lib/relay-hooks/QueryResource.js +31 -101
  82. package/lib/relay-hooks/RelayEnvironmentProvider.js +5 -9
  83. package/lib/relay-hooks/SuspenseResource.js +9 -33
  84. package/lib/relay-hooks/loadEntryPoint.js +19 -31
  85. package/lib/relay-hooks/loadQuery.js +42 -78
  86. package/lib/relay-hooks/preloadQuery_DEPRECATED.js +11 -37
  87. package/lib/relay-hooks/prepareEntryPoint_DEPRECATED.js +9 -15
  88. package/lib/relay-hooks/react-cache/RelayReactCache.js +7 -12
  89. package/lib/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js +27 -81
  90. package/lib/relay-hooks/react-cache/readFragmentInternal_REACT_CACHE.js +206 -0
  91. package/lib/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js +195 -215
  92. package/lib/relay-hooks/react-cache/useFragment_REACT_CACHE.js +5 -15
  93. package/lib/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js +17 -24
  94. package/lib/relay-hooks/react-cache/usePaginationFragment_REACT_CACHE.js +149 -0
  95. package/lib/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js +24 -39
  96. package/lib/relay-hooks/react-cache/useRefetchableFragmentInternal_REACT_CACHE.js +325 -0
  97. package/lib/relay-hooks/react-cache/useRefetchableFragment_REACT_CACHE.js +37 -0
  98. package/lib/relay-hooks/useBlockingPaginationFragment.js +73 -93
  99. package/lib/relay-hooks/useClientQuery.js +30 -0
  100. package/lib/relay-hooks/useEntryPointLoader.js +18 -38
  101. package/lib/relay-hooks/useFetchTrackingRef.js +10 -12
  102. package/lib/relay-hooks/useFragment.js +8 -19
  103. package/lib/relay-hooks/useFragmentNode.js +20 -32
  104. package/lib/relay-hooks/useIsMountedRef.js +4 -6
  105. package/lib/relay-hooks/useIsOperationNodeActive.js +8 -20
  106. package/lib/relay-hooks/useIsParentQueryActive.js +3 -6
  107. package/lib/relay-hooks/useLazyLoadQuery.js +7 -24
  108. package/lib/relay-hooks/useLazyLoadQueryNode.js +23 -34
  109. package/lib/relay-hooks/useLoadMoreFunction.js +46 -78
  110. package/lib/relay-hooks/useMemoOperationDescriptor.js +6 -15
  111. package/lib/relay-hooks/useMemoVariables.js +15 -34
  112. package/lib/relay-hooks/useMutation.js +9 -27
  113. package/lib/relay-hooks/usePaginationFragment.js +73 -76
  114. package/lib/relay-hooks/usePreloadedQuery.js +13 -44
  115. package/lib/relay-hooks/useQueryLoader.js +24 -49
  116. package/lib/relay-hooks/useRefetchableFragment.js +19 -17
  117. package/lib/relay-hooks/useRefetchableFragmentNode.js +65 -109
  118. package/lib/relay-hooks/useRelayEnvironment.js +4 -8
  119. package/lib/relay-hooks/useStaticFragmentNodeWarning.js +4 -8
  120. package/lib/relay-hooks/useSubscribeToInvalidationState.js +8 -9
  121. package/lib/relay-hooks/useSubscription.js +5 -10
  122. package/lib/relay-hooks/useUnsafeRef_DEPRECATED.js +29 -0
  123. package/multi-actor/ActorChange.js.flow +1 -1
  124. package/multi-actor/index.js.flow +1 -1
  125. package/multi-actor/useRelayActorEnvironment.js.flow +2 -4
  126. package/package.json +2 -2
  127. package/react-relay-hooks.js +2 -2
  128. package/react-relay-hooks.min.js +2 -2
  129. package/react-relay-legacy.js +2 -2
  130. package/react-relay-legacy.min.js +2 -2
  131. package/react-relay.js +2 -2
  132. package/react-relay.min.js +2 -2
  133. package/relay-hooks/EntryPointContainer.react.js.flow +3 -5
  134. package/relay-hooks/EntryPointTypes.flow.js.flow +37 -37
  135. package/relay-hooks/FragmentResource.js.flow +43 -19
  136. package/relay-hooks/HooksImplementation.js.flow +7 -9
  137. package/relay-hooks/InternalLogger.js.flow +1 -3
  138. package/relay-hooks/LRUCache.js.flow +1 -3
  139. package/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js.flow +19 -14
  140. package/relay-hooks/MatchContainer.js.flow +6 -8
  141. package/relay-hooks/ProfilerContext.js.flow +1 -3
  142. package/relay-hooks/QueryResource.js.flow +29 -11
  143. package/relay-hooks/RelayEnvironmentProvider.js.flow +4 -6
  144. package/relay-hooks/SuspenseResource.js.flow +1 -3
  145. package/relay-hooks/__flowtests__/EntryPointTypes/EntryPointElementConfig-flowtest.js.flow +6 -4
  146. package/relay-hooks/__flowtests__/EntryPointTypes/NestedEntrypoints-flowtest.js.flow +4 -4
  147. package/relay-hooks/__flowtests__/__generated__/useFragmentFlowtest_user.graphql.js.flow +3 -1
  148. package/relay-hooks/__flowtests__/__generated__/useFragmentFlowtest_users.graphql.js.flow +3 -1
  149. package/relay-hooks/__flowtests__/useBlockingPaginationFragment-flowtest.js.flow +39 -39
  150. package/relay-hooks/__flowtests__/useFragment-flowtest.js.flow +1 -3
  151. package/relay-hooks/__flowtests__/usePaginationFragment-flowtest.js.flow +37 -38
  152. package/relay-hooks/__flowtests__/useRefetchableFragment-flowtest.js.flow +18 -20
  153. package/relay-hooks/__flowtests__/utils.js.flow +21 -12
  154. package/relay-hooks/loadEntryPoint.js.flow +11 -6
  155. package/relay-hooks/loadQuery.js.flow +11 -7
  156. package/relay-hooks/preloadQuery_DEPRECATED.js.flow +9 -12
  157. package/relay-hooks/prepareEntryPoint_DEPRECATED.js.flow +13 -10
  158. package/relay-hooks/react-cache/RelayReactCache.js.flow +1 -3
  159. package/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js.flow +26 -20
  160. package/relay-hooks/react-cache/readFragmentInternal_REACT_CACHE.js.flow +297 -0
  161. package/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js.flow +136 -96
  162. package/relay-hooks/react-cache/useFragment_REACT_CACHE.js.flow +1 -3
  163. package/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js.flow +3 -5
  164. package/relay-hooks/react-cache/usePaginationFragment_REACT_CACHE.js.flow +190 -0
  165. package/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js.flow +3 -6
  166. package/relay-hooks/react-cache/useRefetchableFragmentInternal_REACT_CACHE.js.flow +601 -0
  167. package/relay-hooks/react-cache/useRefetchableFragment_REACT_CACHE.js.flow +65 -0
  168. package/relay-hooks/useBlockingPaginationFragment.js.flow +86 -59
  169. package/relay-hooks/useClientQuery.js.flow +39 -0
  170. package/relay-hooks/useEntryPointLoader.js.flow +16 -14
  171. package/relay-hooks/useFetchTrackingRef.js.flow +7 -8
  172. package/relay-hooks/useFragment.js.flow +2 -4
  173. package/relay-hooks/useFragmentNode.js.flow +7 -8
  174. package/relay-hooks/useIsMountedRef.js.flow +2 -4
  175. package/relay-hooks/useIsOperationNodeActive.js.flow +1 -1
  176. package/relay-hooks/useIsParentQueryActive.js.flow +1 -1
  177. package/relay-hooks/useLazyLoadQuery.js.flow +9 -32
  178. package/relay-hooks/useLazyLoadQueryNode.js.flow +4 -6
  179. package/relay-hooks/useLoadMoreFunction.js.flow +20 -17
  180. package/relay-hooks/useMemoOperationDescriptor.js.flow +3 -5
  181. package/relay-hooks/useMemoVariables.js.flow +13 -31
  182. package/relay-hooks/useMutation.js.flow +6 -8
  183. package/relay-hooks/usePaginationFragment.js.flow +75 -43
  184. package/relay-hooks/usePreloadedQuery.js.flow +49 -43
  185. package/relay-hooks/useQueryLoader.js.flow +89 -28
  186. package/relay-hooks/useRefetchableFragment.js.flow +83 -23
  187. package/relay-hooks/useRefetchableFragmentNode.js.flow +26 -22
  188. package/relay-hooks/useRelayEnvironment.js.flow +2 -4
  189. package/relay-hooks/useStaticFragmentNodeWarning.js.flow +3 -5
  190. package/relay-hooks/useSubscribeToInvalidationState.js.flow +2 -4
  191. package/relay-hooks/useSubscription.js.flow +1 -3
  192. package/relay-hooks/useUnsafeRef_DEPRECATED.js.flow +25 -0
  193. package/lib/readContext.js +0 -28
  194. package/readContext.js.flow +0 -31
@@ -6,10 +6,9 @@
6
6
  *
7
7
  * @flow
8
8
  * @format
9
+ * @oncall relay
9
10
  */
10
11
 
11
- // flowlint ambiguous-object-type:error
12
-
13
12
  'use strict';
14
13
 
15
14
  function getComponentName(component: React$ComponentType<any>): string {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Relay v14.0.0
2
+ * Relay v15.0.0
3
3
  *
4
4
  * Copyright (c) Meta Platforms, Inc. and affiliates.
5
5
  *
@@ -6,10 +6,9 @@
6
6
  *
7
7
  * @flow strict-local
8
8
  * @format
9
+ * @oncall relay
9
10
  */
10
11
 
11
- // flowlint ambiguous-object-type:error
12
-
13
12
  'use strict';
14
13
  import type {RelayContext} from 'relay-runtime/store/RelayStoreTypes';
15
14
 
@@ -6,12 +6,11 @@
6
6
  *
7
7
  * @flow strict-local
8
8
  * @format
9
+ * @oncall relay
9
10
  */
10
11
 
11
- // flowlint ambiguous-object-type:error
12
-
13
12
  'use strict';
14
- import type {GeneratedNodeMap, RelayProp, $RelayProps} from './ReactRelayTypes';
13
+ import type {$RelayProps, GeneratedNodeMap, RelayProp} from './ReactRelayTypes';
15
14
  import type {
16
15
  FragmentMap,
17
16
  FragmentSpecResolver,
@@ -57,6 +56,7 @@ function createContainerWithFragments<
57
56
  const containerName = getContainerName(Component);
58
57
 
59
58
  return class extends React.Component<ContainerProps, ContainerState> {
59
+ // $FlowFixMe[missing-local-annot]
60
60
  static displayName = containerName;
61
61
  constructor(props: $FlowFixMe) {
62
62
  super(props);
@@ -90,7 +90,7 @@ function createContainerWithFragments<
90
90
  static getDerivedStateFromProps(
91
91
  nextProps: ContainerProps,
92
92
  prevState: ContainerState,
93
- ): $Shape<ContainerState> | null {
93
+ ): Partial<ContainerState> | null {
94
94
  // Any props change could impact the query, so we mirror props in state.
95
95
  // This is an unusual pattern, but necessary for this container usecase.
96
96
  const {prevProps} = prevState;
@@ -237,7 +237,9 @@ function createContainerWithFragments<
237
237
  }
238
238
  }
239
239
 
240
+ // $FlowFixMe[missing-local-annot]
240
241
  render() {
242
+ // eslint-disable-next-line no-unused-vars
241
243
  const {componentRef, __relayContext, __rootIsQueryRenderer, ...props} =
242
244
  this.props;
243
245
  return React.createElement(Component, {
@@ -6,10 +6,9 @@
6
6
  *
7
7
  * @flow
8
8
  * @format
9
+ * @oncall relay
9
10
  */
10
11
 
11
- // flowlint ambiguous-object-type:error
12
-
13
12
  'use strict';
14
13
 
15
14
  const ReactRelayContext = require('./ReactRelayContext');
@@ -6,14 +6,14 @@
6
6
  *
7
7
  * @flow strict-local
8
8
  * @format
9
+ * @oncall relay
9
10
  */
10
11
 
11
- // flowlint ambiguous-object-type:error
12
-
13
12
  'use strict';
14
13
 
15
14
  import type {ReactRelayQueryRendererContext as ReactRelayQueryRendererContextType} from './ReactRelayQueryRendererContext';
16
15
  import type {GraphQLTaggedNode, IEnvironment, Variables} from 'relay-runtime';
16
+ import type {SelectorData} from 'relay-runtime/store/RelayStoreTypes';
17
17
 
18
18
  const ReactRelayContext = require('./ReactRelayContext');
19
19
  const ReactRelayQueryRendererContext = require('./ReactRelayQueryRendererContext');
@@ -63,9 +63,9 @@ function ReactRelayLocalQueryRenderer(props: Props): React.Node {
63
63
 
64
64
  // Use a ref to prevent rendering twice when data changes
65
65
  // because of props change
66
- const dataRef = useRef(null);
67
- const [, forceUpdate] = useState(null);
68
- const cleanupFnRef = useRef(null);
66
+ const dataRef = useRef<?SelectorData>(null);
67
+ const [, forceUpdate] = useState<?SelectorData>(null);
68
+ const cleanupFnRef = useRef<null | (() => void)>(null);
69
69
 
70
70
  const snapshot = useMemo(() => {
71
71
  environment.check(operation);
@@ -6,18 +6,18 @@
6
6
  *
7
7
  * @flow
8
8
  * @format
9
+ * @oncall relay
9
10
  */
10
11
 
11
- // flowlint ambiguous-object-type:error
12
-
13
12
  'use strict';
14
13
 
14
+ import type {Sink} from '../relay-runtime/network/RelayObservable';
15
15
  import type {
16
+ $RelayProps,
16
17
  GeneratedNodeMap,
17
18
  ObserverOrCallback,
18
19
  RefetchOptions,
19
20
  RelayPaginationProp,
20
- $RelayProps,
21
21
  } from './ReactRelayTypes';
22
22
  import type {
23
23
  CacheConfig,
@@ -256,9 +256,9 @@ function createGetFragmentVariables(
256
256
  'ReactRelayPaginationContainer: Unable to synthesize a ' +
257
257
  'getFragmentVariables function.',
258
258
  );
259
- return (prevVars: Variables, totalCount: number) => ({
259
+ return (prevVars: Variables, totalCount: number): Variables => ({
260
260
  ...prevVars,
261
- [countVariable]: totalCount,
261
+ [(countVariable: string)]: totalCount,
262
262
  });
263
263
  }
264
264
 
@@ -348,6 +348,7 @@ function createContainerWithFragments<
348
348
  createGetFragmentVariables(metadata);
349
349
 
350
350
  return class extends React.Component<$FlowFixMeProps, ContainerState> {
351
+ // $FlowFixMe[missing-local-annot]
351
352
  static displayName = containerName;
352
353
 
353
354
  _isARequestInFlight: boolean;
@@ -566,6 +567,7 @@ function createContainerWithFragments<
566
567
  ...
567
568
  } {
568
569
  // Extract connection data and verify there are more edges to fetch
570
+ // eslint-disable-next-line no-unused-vars
569
571
  const {componentRef: _, ...restProps} = this.props;
570
572
  const props = {
571
573
  ...restProps,
@@ -696,7 +698,7 @@ function createContainerWithFragments<
696
698
  const observer = toObserver(observerOrCallback);
697
699
  const connectionData = this._getConnectionData();
698
700
  if (!connectionData) {
699
- Observable.create(sink => sink.complete()).subscribe(observer);
701
+ Observable.create<empty>(sink => sink.complete()).subscribe(observer);
700
702
  return null;
701
703
  }
702
704
  const totalCount = connectionData.edgeCount + pageSize;
@@ -757,8 +759,11 @@ function createContainerWithFragments<
757
759
  ): Subscription {
758
760
  const {environment} = assertRelayContext(this.props.__relayContext);
759
761
  const {
762
+ // eslint-disable-next-line no-unused-vars
760
763
  componentRef: _,
764
+ // eslint-disable-next-line no-unused-vars
761
765
  __relayContext,
766
+ // eslint-disable-next-line no-unused-vars
762
767
  __rootIsQueryRenderer,
763
768
  ...restProps
764
769
  } = this.props;
@@ -766,7 +771,7 @@ function createContainerWithFragments<
766
771
  ...restProps,
767
772
  ...this.state.data,
768
773
  };
769
- let fragmentVariables;
774
+ let fragmentVariables: Variables;
770
775
  const rootVariables = getRootVariablesForFragments(fragments, restProps);
771
776
  fragmentVariables = getVariablesFromObject(fragments, restProps);
772
777
  fragmentVariables = {
@@ -774,7 +779,7 @@ function createContainerWithFragments<
774
779
  ...fragmentVariables,
775
780
  ...this._refetchVariables,
776
781
  };
777
- let fetchVariables = connectionConfig.getVariables(
782
+ let fetchVariables: Variables = connectionConfig.getVariables(
778
783
  props,
779
784
  {
780
785
  count: paginatingVariables.count,
@@ -789,14 +794,14 @@ function createContainerWithFragments<
789
794
  fetchVariables,
790
795
  componentName,
791
796
  );
792
- fetchVariables = {
797
+ fetchVariables = ({
793
798
  ...fetchVariables,
794
799
  ...this._refetchVariables,
795
- };
796
- fragmentVariables = {
800
+ }: Variables);
801
+ fragmentVariables = ({
797
802
  ...fetchVariables,
798
803
  ...fragmentVariables,
799
- };
804
+ }: Variables);
800
805
 
801
806
  const cacheConfig: ?CacheConfig = options
802
807
  ? {force: !!options.force}
@@ -867,8 +872,8 @@ function createContainerWithFragments<
867
872
  operation,
868
873
  preservePreviousReferences: true,
869
874
  })
870
- .mergeMap(payload =>
871
- Observable.create(sink => {
875
+ .mergeMap<void>(payload =>
876
+ Observable.create<void>((sink: Sink<void>) => {
872
877
  onNext(payload, () => {
873
878
  sink.next(); // pass void to public observer's `next`
874
879
  sink.complete();
@@ -904,7 +909,9 @@ function createContainerWithFragments<
904
909
  }
905
910
  }
906
911
 
912
+ // $FlowFixMe[missing-local-annot]
907
913
  render() {
914
+ // eslint-disable-next-line no-unused-vars
908
915
  const {componentRef, __relayContext, __rootIsQueryRenderer, ...props} =
909
916
  this.props;
910
917
  return (
@@ -6,10 +6,9 @@
6
6
  *
7
7
  * @flow strict-local
8
8
  * @format
9
+ * @oncall relay
9
10
  */
10
11
 
11
- // flowlint ambiguous-object-type:error
12
-
13
12
  'use strict';
14
13
 
15
14
  import type {
@@ -35,26 +34,26 @@ type OnDataChange = ({
35
34
  }) => void;
36
35
 
37
36
  /** The external API of 'fetch' **/
38
- export type FetchOptions = {|
37
+ export type FetchOptions = {
39
38
  environment: IEnvironment,
40
39
  onDataChange?: null | OnDataChange,
41
40
  operation: OperationDescriptor,
42
- |};
41
+ };
43
42
 
44
43
  // Internally we keep an array of onDataChange callbacks, to support reusing
45
44
  // the queryRenderer for multiple components.
46
- type FetchOptionsInternal = {|
45
+ type FetchOptionsInternal = {
47
46
  environment: IEnvironment,
48
47
  onDataChangeCallbacks: Array<OnDataChange>,
49
48
  operation: OperationDescriptor,
50
- |};
49
+ };
51
50
 
52
- export type ExecuteConfig = {|
51
+ export type ExecuteConfig = {
53
52
  environment: IEnvironment,
54
53
  operation: OperationDescriptor,
55
54
  // Allows pagination container to retain results from previous queries
56
55
  preservePreviousReferences?: boolean,
57
- |};
56
+ };
58
57
 
59
58
  class ReactRelayQueryFetcher {
60
59
  _fetchOptions: ?FetchOptionsInternal;
@@ -64,7 +63,7 @@ class ReactRelayQueryFetcher {
64
63
  _snapshot: ?Snapshot; // results of the root fragment;
65
64
  _error: ?Error; // fetch error
66
65
  _cacheSelectionReference: ?Disposable;
67
- _callOnDataChangeWhenSet: boolean = false;
66
+ _didFetchFinish: boolean = false;
68
67
 
69
68
  constructor(args?: {
70
69
  cacheSelectionReference: ?Disposable,
@@ -77,10 +76,10 @@ class ReactRelayQueryFetcher {
77
76
  }
78
77
  }
79
78
 
80
- getSelectionReferences(): {|
79
+ getSelectionReferences(): {
81
80
  cacheSelectionReference: ?Disposable,
82
81
  selectionReferences: Array<Disposable>,
83
- |} {
82
+ } {
84
83
  return {
85
84
  cacheSelectionReference: this._cacheSelectionReference,
86
85
  selectionReferences: this._selectionReferences,
@@ -104,6 +103,19 @@ class ReactRelayQueryFetcher {
104
103
  return null;
105
104
  }
106
105
 
106
+ getFetchResult(): ?{error?: Error, snapshot?: Snapshot} {
107
+ if (this._didFetchFinish) {
108
+ // We don't reset '_didFetchFinish' because another callback may be set
109
+ if (this._error != null) {
110
+ return {error: this._error};
111
+ } else if (this._snapshot != null) {
112
+ return {snapshot: this._snapshot};
113
+ }
114
+ } else {
115
+ return null;
116
+ }
117
+ }
118
+
107
119
  execute({
108
120
  environment,
109
121
  operation,
@@ -153,8 +165,8 @@ class ReactRelayQueryFetcher {
153
165
  this._fetchOptions.onDataChangeCallbacks || [];
154
166
  this._fetchOptions.onDataChangeCallbacks.push(onDataChange);
155
167
 
156
- if (this._callOnDataChangeWhenSet) {
157
- // We don't reset '_callOnDataChangeWhenSet' because another callback may be set
168
+ if (this._didFetchFinish) {
169
+ // We don't reset '_didFetchFinish' because another callback may be set
158
170
  if (this._error != null) {
159
171
  onDataChange({error: this._error});
160
172
  } else if (this._snapshot != null) {
@@ -217,7 +229,7 @@ class ReactRelayQueryFetcher {
217
229
  next: () => {
218
230
  // If we received a response,
219
231
  // Make a note that to notify the callback when it's later added.
220
- this._callOnDataChangeWhenSet = true;
232
+ this._didFetchFinish = true;
221
233
  this._error = null;
222
234
 
223
235
  // Only notify of the first result if `next` is being called **asynchronously**
@@ -227,7 +239,7 @@ class ReactRelayQueryFetcher {
227
239
  error: err => {
228
240
  // If we received a response when we didn't have a change callback,
229
241
  // Make a note that to notify the callback when it's later added.
230
- this._callOnDataChangeWhenSet = true;
242
+ this._didFetchFinish = true;
231
243
  this._error = err;
232
244
  this._snapshot = null;
233
245
 
@@ -321,7 +333,7 @@ class ReactRelayQueryFetcher {
321
333
  }: {
322
334
  notifyFirstResult: boolean,
323
335
  ...
324
- }) {
336
+ }): void {
325
337
  invariant(
326
338
  this._fetchOptions,
327
339
  'ReactRelayQueryFetcher: `_onQueryDataAvailable` should have been called after having called `fetch`',
@@ -6,10 +6,9 @@
6
6
  *
7
7
  * @flow
8
8
  * @format
9
+ * @oncall relay
9
10
  */
10
11
 
11
- // flowlint ambiguous-object-type:error
12
-
13
12
  'use strict';
14
13
 
15
14
  import type {ReactRelayQueryRendererContext as ReactRelayQueryRendererContextType} from './ReactRelayQueryRendererContext';
@@ -28,13 +27,14 @@ const ReactRelayQueryFetcher = require('./ReactRelayQueryFetcher');
28
27
  const ReactRelayQueryRendererContext = require('./ReactRelayQueryRendererContext');
29
28
  const areEqual = require('areEqual');
30
29
  const React = require('react');
30
+ const {RelayFeatureFlags} = require('relay-runtime');
31
31
  const {
32
32
  createOperationDescriptor,
33
33
  deepFreeze,
34
34
  getRequest,
35
35
  } = require('relay-runtime');
36
36
 
37
- type RetryCallbacks = {|
37
+ type RetryCallbacks = {
38
38
  handleDataChange:
39
39
  | null
40
40
  | (({
@@ -43,39 +43,39 @@ type RetryCallbacks = {|
43
43
  ...
44
44
  }) => void),
45
45
  handleRetryAfterError: null | ((error: Error) => void),
46
- |};
46
+ };
47
47
 
48
- export type RenderProps<T> = {|
48
+ export type RenderProps<T> = {
49
49
  error: ?Error,
50
50
  props: ?T,
51
51
  retry: ?(cacheConfigOverride?: CacheConfig) => void,
52
- |};
52
+ };
53
53
  /**
54
54
  * React may double-fire the constructor, and we call 'fetch' in the
55
55
  * constructor. If a request is already in flight from a previous call to the
56
56
  * constructor, just reuse the query fetcher and wait for the response.
57
57
  */
58
58
  const requestCache: {
59
- [string]: void | {|
59
+ [string]: void | {
60
60
  queryFetcher: ReactRelayQueryFetcher,
61
61
  snapshot: ?Snapshot,
62
- |},
62
+ },
63
63
  } = {};
64
64
 
65
65
  const queryRendererContext: ReactRelayQueryRendererContextType = {
66
66
  rootIsQueryRenderer: true,
67
67
  };
68
68
 
69
- export type Props = {|
69
+ export type Props = {
70
70
  cacheConfig?: ?CacheConfig,
71
71
  fetchPolicy?: 'store-and-network' | 'network-only',
72
72
  environment: IEnvironment,
73
73
  query: ?GraphQLTaggedNode,
74
74
  render: (renderProps: RenderProps<Object>) => React.Node,
75
75
  variables: Variables,
76
- |};
76
+ };
77
77
 
78
- type State = {|
78
+ type State = {
79
79
  error: Error | null,
80
80
  prevPropsEnvironment: IEnvironment,
81
81
  prevPropsVariables: Variables,
@@ -86,7 +86,7 @@ type State = {|
86
86
  retryCallbacks: RetryCallbacks,
87
87
  requestCacheKey: ?string,
88
88
  snapshot: Snapshot | null,
89
- |};
89
+ };
90
90
 
91
91
  /**
92
92
  * @public
@@ -171,7 +171,36 @@ class ReactRelayQueryRenderer extends React.Component<Props, State> {
171
171
  this._maybeHiddenOrFastRefresh = false;
172
172
  // eslint-disable-next-line react/no-did-mount-set-state
173
173
  this.setState(prevState => {
174
- return resetQueryStateForUpdate(this.props, prevState);
174
+ const newState = resetQueryStateForUpdate(this.props, prevState);
175
+ const {requestCacheKey, queryFetcher} = newState;
176
+ if (requestCacheKey != null && requestCache[requestCacheKey] != null) {
177
+ if (RelayFeatureFlags.ENABLE_QUERY_RENDERER_SET_STATE_PREVENTION) {
178
+ const fetchResult = queryFetcher.getFetchResult();
179
+ if (fetchResult != null) {
180
+ const snapshot = fetchResult.snapshot ?? null;
181
+ const error = fetchResult.error ?? null;
182
+
183
+ const {requestCacheKey: prevRequestCacheKey} = prevState;
184
+ if (prevRequestCacheKey != null) {
185
+ delete requestCache[prevRequestCacheKey];
186
+ }
187
+
188
+ newState.renderProps = getRenderProps(
189
+ error,
190
+ snapshot,
191
+ queryFetcher,
192
+ prevState.retryCallbacks,
193
+ );
194
+ newState.snapshot = snapshot;
195
+ newState.requestCacheKey = null;
196
+ } else {
197
+ queryFetcher.setOnDataChange(this._handleDataChange);
198
+ }
199
+ } else {
200
+ queryFetcher.setOnDataChange(this._handleDataChange);
201
+ }
202
+ }
203
+ return newState;
175
204
  });
176
205
  return;
177
206
  }
@@ -6,14 +6,13 @@
6
6
  *
7
7
  * @flow strict-local
8
8
  * @format
9
+ * @oncall relay
9
10
  */
10
11
 
11
- // flowlint ambiguous-object-type:error
12
-
13
12
  'use strict';
14
13
  const React = require('react');
15
14
 
16
- export type ReactRelayQueryRendererContext = {|rootIsQueryRenderer: boolean|};
15
+ export type ReactRelayQueryRendererContext = {rootIsQueryRenderer: boolean};
17
16
 
18
17
  module.exports = (React.createContext({
19
18
  rootIsQueryRenderer: false,
@@ -6,18 +6,17 @@
6
6
  *
7
7
  * @flow
8
8
  * @format
9
+ * @oncall relay
9
10
  */
10
11
 
11
- // flowlint ambiguous-object-type:error
12
-
13
12
  'use strict';
14
13
 
15
14
  import type {
15
+ $RelayProps,
16
16
  GeneratedNodeMap,
17
17
  ObserverOrCallback,
18
18
  RefetchOptions,
19
19
  RelayRefetchProp,
20
- $RelayProps,
21
20
  } from './ReactRelayTypes';
22
21
  import type {
23
22
  CacheConfig,
@@ -81,6 +80,7 @@ function createContainerWithFragments<
81
80
  const containerName = getContainerName(Component);
82
81
 
83
82
  return class extends React.Component<ContainerProps, ContainerState> {
83
+ // $FlowFixMe[missing-local-annot]
84
84
  static displayName = containerName;
85
85
 
86
86
  _refetchSubscription: ?Subscription;
@@ -144,7 +144,7 @@ function createContainerWithFragments<
144
144
  static getDerivedStateFromProps(
145
145
  nextProps: ContainerProps,
146
146
  prevState: ContainerState,
147
- ): $Shape<ContainerState> | null {
147
+ ): Partial<ContainerState> | null {
148
148
  // Any props change could impact the query, so we mirror props in state.
149
149
  // This is an unusual pattern, but necessary for this container usecase.
150
150
  const {prevProps} = prevState;
@@ -364,16 +364,14 @@ function createContainerWithFragments<
364
364
  );
365
365
 
366
366
  // TODO: T26288752 find a better way
367
- /* eslint-disable lint/react-state-props-mutation */
368
367
  this.state.localVariables = fetchVariables;
369
- /* eslint-enable lint/react-state-props-mutation */
370
368
 
371
369
  // Cancel any previously running refetch.
372
370
  this._refetchSubscription && this._refetchSubscription.unsubscribe();
373
371
 
374
372
  // Declare refetchSubscription before assigning it in .start(), since
375
373
  // synchronous completion may call callbacks .subscribe() returns.
376
- let refetchSubscription;
374
+ let refetchSubscription: Subscription;
377
375
 
378
376
  const storeSnapshot = this._getQueryFetcher().lookupInStore(
379
377
  environment,
@@ -409,12 +407,12 @@ function createContainerWithFragments<
409
407
  // TODO (T26430099): Cleanup old references
410
408
  preservePreviousReferences: true,
411
409
  })
412
- .mergeMap(response => {
410
+ .mergeMap<void>(response => {
413
411
  this.state.resolver.setVariables(
414
412
  fragmentVariables,
415
413
  operation.request.node,
416
414
  );
417
- return Observable.create(sink =>
415
+ return Observable.create<void>(sink =>
418
416
  this.setState(
419
417
  latestState => ({
420
418
  data: latestState.resolver.resolve(),
@@ -451,7 +449,9 @@ function createContainerWithFragments<
451
449
  };
452
450
  };
453
451
 
452
+ // $FlowFixMe[missing-local-annot]
454
453
  render() {
454
+ // eslint-disable-next-line no-unused-vars
455
455
  const {componentRef, __relayContext, __rootIsQueryRenderer, ...props} =
456
456
  this.props;
457
457
  const {relayProp, contextForChildren} = this.state;
@@ -6,15 +6,15 @@
6
6
  *
7
7
  * @flow
8
8
  * @format
9
+ * @oncall relay
9
10
  */
10
11
 
11
- // flowlint ambiguous-object-type:error
12
-
13
12
  'use strict';
14
13
 
15
14
  import type {
16
15
  CacheConfig,
17
16
  ConcreteRequest,
17
+ GraphQLResponse,
18
18
  GraphQLSingularResponse,
19
19
  IEnvironment,
20
20
  PayloadError,
@@ -147,7 +147,7 @@ class ReactRelayTestMocker {
147
147
  ) => {
148
148
  let resolve;
149
149
  let reject;
150
- const promise = new Promise((res, rej) => {
150
+ const promise = new Promise<GraphQLResponse>((res, rej) => {
151
151
  resolve = res;
152
152
  reject = rej;
153
153
  });
@@ -6,10 +6,9 @@
6
6
  *
7
7
  * @flow strict-local
8
8
  * @format
9
+ * @oncall relay
9
10
  */
10
11
 
11
- // flowlint ambiguous-object-type:error
12
-
13
12
  'use strict';
14
13
 
15
14
  import type {
@@ -29,7 +28,7 @@ export type ObserverOrCallback = Observer<void> | ((error: ?Error) => mixed);
29
28
  // RelayRefetchProp to flow into a RelayProp.
30
29
  export type RelayProp = {+environment: IEnvironment, ...};
31
30
 
32
- export type RelayPaginationProp = {|
31
+ export type RelayPaginationProp = {
33
32
  +environment: IEnvironment,
34
33
  +hasMore: () => boolean,
35
34
  +isLoading: () => boolean,
@@ -43,9 +42,9 @@ export type RelayPaginationProp = {|
43
42
  observerOrCallback: ?ObserverOrCallback,
44
43
  refetchVariables: ?Variables,
45
44
  ) => ?Disposable,
46
- |};
45
+ };
47
46
 
48
- export type RelayRefetchProp = {|
47
+ export type RelayRefetchProp = {
49
48
  +environment: IEnvironment,
50
49
  +refetch: (
51
50
  refetchVariables: Variables | ((fragmentVariables: Variables) => Variables),
@@ -53,13 +52,13 @@ export type RelayRefetchProp = {|
53
52
  observerOrCallback: ?ObserverOrCallback,
54
53
  options?: RefetchOptions,
55
54
  ) => Disposable,
56
- |};
55
+ };
57
56
 
58
- export type RefetchOptions = {|
57
+ export type RefetchOptions = {
59
58
  +force?: boolean,
60
59
  +fetchPolicy?: 'store-or-network' | 'network-only',
61
60
  +metadata?: {[key: string]: mixed, ...},
62
- |};
61
+ };
63
62
 
64
63
  /**
65
64
  * A utility type which takes the type of a fragment's data (typically found in
@@ -6,10 +6,9 @@
6
6
  *
7
7
  * @flow
8
8
  * @format
9
+ * @oncall relay
9
10
  */
10
11
 
11
- // flowlint ambiguous-object-type:error
12
-
13
12
  'use strict';
14
13
 
15
14
  import type {RelayContext} from 'relay-runtime';