react-relay 11.0.2 → 13.0.0-rc.2

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 (177) hide show
  1. package/README.md +47 -0
  2. package/ReactRelayContainerUtils.js.flow +1 -1
  3. package/ReactRelayContext.js +1 -1
  4. package/ReactRelayContext.js.flow +3 -4
  5. package/ReactRelayFragmentContainer.js.flow +25 -25
  6. package/ReactRelayFragmentMockRenderer.js.flow +2 -2
  7. package/ReactRelayLocalQueryRenderer.js.flow +7 -8
  8. package/ReactRelayPaginationContainer.js.flow +112 -59
  9. package/ReactRelayQueryFetcher.js.flow +10 -11
  10. package/ReactRelayQueryRenderer.js.flow +116 -82
  11. package/ReactRelayQueryRendererContext.js.flow +1 -1
  12. package/ReactRelayRefetchContainer.js.flow +42 -39
  13. package/ReactRelayTestMocker.js.flow +17 -15
  14. package/ReactRelayTypes.js.flow +11 -11
  15. package/RelayContext.js.flow +4 -4
  16. package/__flowtests__/ReactRelayFragmentContainer-flowtest.js.flow +2 -3
  17. package/__flowtests__/ReactRelayPaginationContainer-flowtest.js.flow +12 -8
  18. package/__flowtests__/ReactRelayRefetchContainer-flowtest.js.flow +11 -7
  19. package/__flowtests__/RelayModern-flowtest.js.flow +79 -47
  20. package/__flowtests__/RelayModernFlowtest_badref.graphql.js.flow +6 -5
  21. package/__flowtests__/RelayModernFlowtest_notref.graphql.js.flow +6 -5
  22. package/__flowtests__/RelayModernFlowtest_user.graphql.js.flow +5 -4
  23. package/__flowtests__/RelayModernFlowtest_users.graphql.js.flow +5 -4
  24. package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer.graphql.js.flow +72 -0
  25. package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer2.graphql.js.flow +72 -0
  26. package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtestQuery.graphql.js.flow +227 -0
  27. package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtest_viewer.graphql.js.flow +164 -0
  28. package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtestQuery.graphql.js.flow +227 -0
  29. package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtest_viewer.graphql.js.flow +164 -0
  30. package/__flowtests__/__generated__/RelayModernFlowtest_badref.graphql.js.flow +66 -0
  31. package/__flowtests__/__generated__/RelayModernFlowtest_notref.graphql.js.flow +66 -0
  32. package/__flowtests__/__generated__/RelayModernFlowtest_user.graphql.js.flow +59 -0
  33. package/__flowtests__/__generated__/RelayModernFlowtest_users.graphql.js.flow +61 -0
  34. package/assertFragmentMap.js.flow +3 -3
  35. package/buildReactRelayContainer.js.flow +12 -11
  36. package/getRootVariablesForFragments.js.flow +3 -5
  37. package/hooks.js +1 -1
  38. package/hooks.js.flow +6 -7
  39. package/index.js +1 -1
  40. package/index.js.flow +7 -8
  41. package/isRelayEnvironment.js.flow +1 -1
  42. package/jest-react/enqueueTask.js.flow +56 -0
  43. package/jest-react/index.js.flow +12 -0
  44. package/jest-react/internalAct.js.flow +138 -0
  45. package/legacy.js +1 -1
  46. package/legacy.js.flow +1 -1
  47. package/lib/ReactRelayContainerUtils.js +1 -1
  48. package/lib/ReactRelayContext.js +1 -1
  49. package/lib/ReactRelayFragmentContainer.js +22 -16
  50. package/lib/ReactRelayFragmentMockRenderer.js +3 -3
  51. package/lib/ReactRelayLocalQueryRenderer.js +8 -9
  52. package/lib/ReactRelayPaginationContainer.js +97 -39
  53. package/lib/ReactRelayQueryFetcher.js +3 -3
  54. package/lib/ReactRelayQueryRenderer.js +87 -54
  55. package/lib/ReactRelayQueryRendererContext.js +1 -1
  56. package/lib/ReactRelayRefetchContainer.js +39 -26
  57. package/lib/ReactRelayTestMocker.js +8 -9
  58. package/lib/ReactRelayTypes.js +1 -1
  59. package/lib/RelayContext.js +4 -3
  60. package/lib/assertFragmentMap.js +3 -2
  61. package/lib/buildReactRelayContainer.js +8 -8
  62. package/lib/getRootVariablesForFragments.js +2 -3
  63. package/lib/hooks.js +6 -6
  64. package/lib/index.js +8 -8
  65. package/lib/isRelayEnvironment.js +1 -1
  66. package/lib/jest-react/enqueueTask.js +53 -0
  67. package/lib/jest-react/index.js +13 -0
  68. package/lib/jest-react/internalAct.js +115 -0
  69. package/lib/legacy.js +1 -1
  70. package/lib/multi-actor/ActorChange.js +30 -0
  71. package/lib/multi-actor/index.js +11 -0
  72. package/lib/multi-actor/useRelayActorEnvironment.js +29 -0
  73. package/lib/readContext.js +1 -1
  74. package/lib/relay-hooks/EntryPointContainer.react.js +4 -4
  75. package/lib/relay-hooks/EntryPointTypes.flow.js +1 -1
  76. package/lib/relay-hooks/FragmentResource.js +342 -89
  77. package/lib/relay-hooks/InternalLogger.js +1 -1
  78. package/lib/relay-hooks/LRUCache.js +1 -1
  79. package/lib/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js +5 -5
  80. package/lib/relay-hooks/MatchContainer.js +2 -2
  81. package/lib/relay-hooks/ProfilerContext.js +1 -1
  82. package/lib/relay-hooks/QueryResource.js +172 -29
  83. package/lib/relay-hooks/RelayEnvironmentProvider.js +6 -4
  84. package/lib/relay-hooks/SuspenseResource.js +130 -0
  85. package/lib/relay-hooks/loadEntryPoint.js +1 -1
  86. package/lib/relay-hooks/loadQuery.js +42 -20
  87. package/lib/relay-hooks/preloadQuery_DEPRECATED.js +25 -16
  88. package/lib/relay-hooks/prepareEntryPoint_DEPRECATED.js +1 -1
  89. package/lib/relay-hooks/useBlockingPaginationFragment.js +5 -6
  90. package/lib/relay-hooks/useEntryPointLoader.js +3 -3
  91. package/lib/relay-hooks/useFetchTrackingRef.js +3 -2
  92. package/lib/relay-hooks/useFragment.js +7 -7
  93. package/lib/relay-hooks/useFragmentNode.js +5 -5
  94. package/lib/relay-hooks/useIsMountedRef.js +1 -1
  95. package/lib/relay-hooks/useIsOperationNodeActive.js +3 -3
  96. package/lib/relay-hooks/useIsParentQueryActive.js +1 -1
  97. package/lib/relay-hooks/useLazyLoadQuery.js +4 -4
  98. package/lib/relay-hooks/useLazyLoadQueryNode.js +11 -5
  99. package/lib/relay-hooks/useLoadMoreFunction.js +9 -13
  100. package/lib/relay-hooks/useMemoOperationDescriptor.js +3 -3
  101. package/lib/relay-hooks/useMemoVariables.js +3 -3
  102. package/lib/relay-hooks/useMutation.js +18 -7
  103. package/lib/relay-hooks/usePaginationFragment.js +3 -4
  104. package/lib/relay-hooks/usePreloadedQuery.js +6 -6
  105. package/lib/relay-hooks/useQueryLoader.js +31 -11
  106. package/lib/relay-hooks/useRefetchableFragment.js +1 -1
  107. package/lib/relay-hooks/useRefetchableFragmentNode.js +14 -18
  108. package/lib/relay-hooks/useRelayEnvironment.js +3 -3
  109. package/lib/relay-hooks/useStaticFragmentNodeWarning.js +3 -3
  110. package/lib/relay-hooks/useSubscribeToInvalidationState.js +3 -2
  111. package/lib/relay-hooks/useSubscription.js +11 -8
  112. package/multi-actor/ActorChange.js.flow +58 -0
  113. package/multi-actor/index.js.flow +14 -0
  114. package/multi-actor/useRelayActorEnvironment.js.flow +49 -0
  115. package/package.json +3 -3
  116. package/react-relay-hooks.js +2 -2
  117. package/react-relay-hooks.min.js +2 -2
  118. package/react-relay-legacy.js +2 -2
  119. package/react-relay-legacy.min.js +2 -2
  120. package/react-relay.js +2 -2
  121. package/react-relay.min.js +2 -2
  122. package/readContext.js.flow +1 -1
  123. package/relay-hooks/EntryPointContainer.react.js.flow +9 -16
  124. package/relay-hooks/EntryPointTypes.flow.js.flow +25 -26
  125. package/relay-hooks/FragmentResource.js.flow +359 -93
  126. package/relay-hooks/InternalLogger.js.flow +1 -1
  127. package/relay-hooks/LRUCache.js.flow +1 -1
  128. package/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js.flow +33 -47
  129. package/relay-hooks/MatchContainer.js.flow +4 -3
  130. package/relay-hooks/ProfilerContext.js.flow +1 -1
  131. package/relay-hooks/QueryResource.js.flow +217 -26
  132. package/relay-hooks/RelayEnvironmentProvider.js.flow +15 -5
  133. package/relay-hooks/SuspenseResource.js.flow +115 -0
  134. package/relay-hooks/__flowtests__/EntryPointTypes/EntryPointElementConfig-flowtest.js.flow +5 -4
  135. package/relay-hooks/__flowtests__/EntryPointTypes/NestedEntrypoints-flowtest.js.flow +2 -2
  136. package/relay-hooks/__flowtests__/__generated__/useFragmentFlowtest_user.graphql.js.flow +59 -0
  137. package/relay-hooks/__flowtests__/__generated__/useFragmentFlowtest_users.graphql.js.flow +61 -0
  138. package/relay-hooks/__flowtests__/useBlockingPaginationFragment-flowtest.js.flow +11 -10
  139. package/relay-hooks/__flowtests__/useFragment-flowtest.js.flow +55 -32
  140. package/relay-hooks/__flowtests__/usePaginationFragment-flowtest.js.flow +11 -10
  141. package/relay-hooks/__flowtests__/useRefetchableFragment-flowtest.js.flow +11 -10
  142. package/relay-hooks/__flowtests__/utils.js.flow +21 -32
  143. package/relay-hooks/loadEntryPoint.js.flow +7 -13
  144. package/relay-hooks/loadQuery.js.flow +50 -32
  145. package/relay-hooks/preloadQuery_DEPRECATED.js.flow +31 -22
  146. package/relay-hooks/prepareEntryPoint_DEPRECATED.js.flow +7 -13
  147. package/relay-hooks/useBlockingPaginationFragment.js.flow +14 -12
  148. package/relay-hooks/useEntryPointLoader.js.flow +8 -11
  149. package/relay-hooks/useFetchTrackingRef.js.flow +3 -3
  150. package/relay-hooks/useFragment.js.flow +31 -62
  151. package/relay-hooks/useFragmentNode.js.flow +6 -8
  152. package/relay-hooks/useIsMountedRef.js.flow +1 -1
  153. package/relay-hooks/useIsOperationNodeActive.js.flow +4 -6
  154. package/relay-hooks/useIsParentQueryActive.js.flow +4 -5
  155. package/relay-hooks/useLazyLoadQuery.js.flow +14 -16
  156. package/relay-hooks/useLazyLoadQueryNode.js.flow +20 -14
  157. package/relay-hooks/useLoadMoreFunction.js.flow +21 -30
  158. package/relay-hooks/useMemoOperationDescriptor.js.flow +6 -8
  159. package/relay-hooks/useMemoVariables.js.flow +7 -7
  160. package/relay-hooks/useMutation.js.flow +27 -27
  161. package/relay-hooks/usePaginationFragment.js.flow +39 -45
  162. package/relay-hooks/usePreloadedQuery.js.flow +14 -20
  163. package/relay-hooks/useQueryLoader.js.flow +42 -23
  164. package/relay-hooks/useRefetchableFragment.js.flow +8 -9
  165. package/relay-hooks/useRefetchableFragmentNode.js.flow +25 -33
  166. package/relay-hooks/useRelayEnvironment.js.flow +3 -5
  167. package/relay-hooks/useStaticFragmentNodeWarning.js.flow +3 -4
  168. package/relay-hooks/useSubscribeToInvalidationState.js.flow +4 -7
  169. package/relay-hooks/useSubscription.js.flow +21 -11
  170. package/lib/relay-hooks/getPaginationMetadata.js +0 -41
  171. package/lib/relay-hooks/getPaginationVariables.js +0 -67
  172. package/lib/relay-hooks/getRefetchMetadata.js +0 -36
  173. package/lib/relay-hooks/getValueAtPath.js +0 -51
  174. package/relay-hooks/getPaginationMetadata.js.flow +0 -74
  175. package/relay-hooks/getPaginationVariables.js.flow +0 -110
  176. package/relay-hooks/getRefetchMetadata.js.flow +0 -80
  177. package/relay-hooks/getValueAtPath.js.flow +0 -46
package/README.md ADDED
@@ -0,0 +1,47 @@
1
+ React APIs for Relay
2
+ ---
3
+
4
+ This package contains a collection of React APIs: Hooks and Components that are integrated with Relay runtime.
5
+
6
+ Example:
7
+
8
+ ```js
9
+
10
+ // @flow
11
+
12
+ import type {UserComponent_user$key} from 'UserComponent_user.graphql';
13
+
14
+ const React = require('react');
15
+
16
+ const {graphql, useFragment} = require('react-relay');
17
+
18
+ type Props = {
19
+ user: UserComponent_user$key,
20
+ };
21
+
22
+ function UserComponent(props: Props) {
23
+ const data = useFragment(
24
+ graphql`
25
+ fragment UserComponent_user on User {
26
+ name
27
+ profile_picture(scale: 2) {
28
+ uri
29
+ }
30
+ }
31
+ `,
32
+ props.user,
33
+ );
34
+
35
+ return (
36
+ <>
37
+ <h1>{data.name}</h1>
38
+ <div>
39
+ <img src={data.profile_picture?.uri} />
40
+ </div>
41
+ </>
42
+ );
43
+ }
44
+
45
+ ```
46
+
47
+ For complete API reference, visit https://relay.dev/.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Relay v11.0.2
2
+ * Relay v13.0.0-rc.2
3
3
  *
4
4
  * Copyright (c) Facebook, Inc. and its affiliates.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -11,14 +11,13 @@
11
11
  // flowlint ambiguous-object-type:error
12
12
 
13
13
  'use strict';
14
- const React = require('react');
14
+ import type {RelayContext} from 'relay-runtime/store/RelayStoreTypes';
15
15
 
16
+ const React = require('react');
16
17
  const {
17
18
  __internal: {createRelayContext},
18
19
  } = require('relay-runtime');
19
20
 
20
- import type {RelayContext} from 'relay-runtime/store/RelayStoreTypes';
21
-
22
21
  module.exports = (createRelayContext(
23
22
  React,
24
23
  ): React$Context<RelayContext | null>);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -12,27 +12,24 @@
12
12
 
13
13
  'use strict';
14
14
 
15
- const React = require('react');
15
+ import type {GeneratedNodeMap, RelayProp, $RelayProps} from './ReactRelayTypes';
16
+ import type {
17
+ FragmentMap,
18
+ FragmentSpecResolver,
19
+ RelayContext,
20
+ } from 'relay-runtime';
16
21
 
17
- const areEqual = require('areEqual');
18
22
  const buildReactRelayContainer = require('./buildReactRelayContainer');
19
- const getRootVariablesForFragments = require('./getRootVariablesForFragments');
20
-
21
23
  const {getContainerName} = require('./ReactRelayContainerUtils');
22
24
  const {assertRelayContext} = require('./RelayContext');
25
+ const areEqual = require('areEqual');
26
+ const React = require('react');
23
27
  const {
24
28
  createFragmentSpecResolver,
25
29
  getDataIDsFromObject,
26
30
  isScalarAndEqual,
27
31
  } = require('relay-runtime');
28
32
 
29
- import type {$RelayProps, GeneratedNodeMap, RelayProp} from './ReactRelayTypes';
30
- import type {
31
- FragmentMap,
32
- FragmentSpecResolver,
33
- RelayContext,
34
- } from 'relay-runtime';
35
-
36
33
  type ContainerProps = $FlowFixMeProps;
37
34
  type ContainerState = {
38
35
  data: {[key: string]: mixed, ...},
@@ -149,17 +146,17 @@ function createContainerWithFragments<
149
146
  }
150
147
 
151
148
  componentDidMount() {
152
- this._subscribeToNewResolver();
153
- this._rerenderIfStoreHasChanged();
149
+ this._subscribeToNewResolverAndRerenderIfStoreHasChanged();
154
150
  }
155
151
 
156
152
  componentDidUpdate(prevProps: ContainerProps, prevState: ContainerState) {
157
153
  if (this.state.resolver !== prevState.resolver) {
158
154
  prevState.resolver.dispose();
159
155
 
160
- this._subscribeToNewResolver();
156
+ this._subscribeToNewResolverAndRerenderIfStoreHasChanged();
157
+ } else {
158
+ this._rerenderIfStoreHasChanged();
161
159
  }
162
- this._rerenderIfStoreHasChanged();
163
160
  }
164
161
 
165
162
  componentWillUnmount() {
@@ -222,21 +219,24 @@ function createContainerWithFragments<
222
219
  }
223
220
  }
224
221
 
225
- _subscribeToNewResolver() {
226
- const {resolver} = this.state;
222
+ _subscribeToNewResolverAndRerenderIfStoreHasChanged() {
223
+ const {data, resolver} = this.state;
224
+ const maybeNewData = resolver.resolve();
227
225
 
228
226
  // Event listeners are only safe to add during the commit phase,
229
227
  // So they won't leak if render is interrupted or errors.
230
- resolver.setCallback(this._handleFragmentDataUpdate);
228
+ resolver.setCallback(this.props, this._handleFragmentDataUpdate);
229
+
230
+ // External values could change between render and commit.
231
+ // Check for this case, even though it requires an extra store read.
232
+ if (data !== maybeNewData) {
233
+ this.setState({data: maybeNewData});
234
+ }
231
235
  }
232
236
 
233
237
  render() {
234
- const {
235
- componentRef,
236
- __relayContext,
237
- __rootIsQueryRenderer,
238
- ...props
239
- } = this.props;
238
+ const {componentRef, __relayContext, __rootIsQueryRenderer, ...props} =
239
+ this.props;
240
240
  return React.createElement(Component, {
241
241
  ...props,
242
242
  ...this.state.data,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -12,8 +12,8 @@
12
12
 
13
13
  'use strict';
14
14
 
15
- const React = require('react');
16
15
  const ReactRelayContext = require('./ReactRelayContext');
16
+ const React = require('react');
17
17
 
18
18
  function ReactRelayFragmentMockRenderer(props: Object): React.Node {
19
19
  return (
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -12,21 +12,20 @@
12
12
 
13
13
  'use strict';
14
14
 
15
- const React = require('react');
15
+ import type {ReactRelayQueryRendererContext as ReactRelayQueryRendererContextType} from './ReactRelayQueryRendererContext';
16
+ import type {GraphQLTaggedNode, IEnvironment, Variables} from 'relay-runtime';
17
+
16
18
  const ReactRelayContext = require('./ReactRelayContext');
17
19
  const ReactRelayQueryRendererContext = require('./ReactRelayQueryRendererContext');
18
-
19
- const {useLayoutEffect, useState, useRef, useMemo} = React;
20
+ const areEqual = require('areEqual');
21
+ const React = require('react');
20
22
  const {
21
23
  createOperationDescriptor,
22
24
  deepFreeze,
23
25
  getRequest,
24
26
  } = require('relay-runtime');
25
27
 
26
- const areEqual = require('areEqual');
27
-
28
- import type {ReactRelayQueryRendererContext as ReactRelayQueryRendererContextType} from './ReactRelayQueryRendererContext';
29
- import type {GraphQLTaggedNode, IEnvironment, Variables} from 'relay-runtime';
28
+ const {useLayoutEffect, useState, useRef, useMemo} = React;
30
29
 
31
30
  type Props = {
32
31
  environment: IEnvironment,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -12,39 +12,12 @@
12
12
 
13
13
  'use strict';
14
14
 
15
- const React = require('react');
16
- const ReactRelayContext = require('./ReactRelayContext');
17
- const ReactRelayQueryFetcher = require('./ReactRelayQueryFetcher');
18
-
19
- const areEqual = require('areEqual');
20
- const buildReactRelayContainer = require('./buildReactRelayContainer');
21
- const getRootVariablesForFragments = require('./getRootVariablesForFragments');
22
- const invariant = require('invariant');
23
- const warning = require('warning');
24
-
25
- const {
26
- getComponentName,
27
- getContainerName,
28
- } = require('./ReactRelayContainerUtils');
29
- const {assertRelayContext} = require('./RelayContext');
30
- const {
31
- ConnectionInterface,
32
- Observable,
33
- createFragmentSpecResolver,
34
- createOperationDescriptor,
35
- getDataIDsFromObject,
36
- getRequest,
37
- getSelector,
38
- getVariablesFromObject,
39
- isScalarAndEqual,
40
- } = require('relay-runtime');
41
-
42
15
  import type {
43
- $RelayProps,
44
- ObserverOrCallback,
45
16
  GeneratedNodeMap,
17
+ ObserverOrCallback,
46
18
  RefetchOptions,
47
19
  RelayPaginationProp,
20
+ $RelayProps,
48
21
  } from './ReactRelayTypes';
49
22
  import type {
50
23
  CacheConfig,
@@ -60,11 +33,37 @@ import type {
60
33
  Variables,
61
34
  } from 'relay-runtime';
62
35
 
36
+ const buildReactRelayContainer = require('./buildReactRelayContainer');
37
+ const getRootVariablesForFragments = require('./getRootVariablesForFragments');
38
+ const {
39
+ getComponentName,
40
+ getContainerName,
41
+ } = require('./ReactRelayContainerUtils');
42
+ const ReactRelayContext = require('./ReactRelayContext');
43
+ const ReactRelayQueryFetcher = require('./ReactRelayQueryFetcher');
44
+ const {assertRelayContext} = require('./RelayContext');
45
+ const areEqual = require('areEqual');
46
+ const invariant = require('invariant');
47
+ const React = require('react');
48
+ const {
49
+ ConnectionInterface,
50
+ Observable,
51
+ RelayFeatureFlags,
52
+ createFragmentSpecResolver,
53
+ createOperationDescriptor,
54
+ getDataIDsFromObject,
55
+ getRequest,
56
+ getVariablesFromObject,
57
+ isScalarAndEqual,
58
+ } = require('relay-runtime');
59
+ const warning = require('warning');
60
+
63
61
  type ContainerState = {
64
62
  data: {[key: string]: mixed, ...},
65
63
  relayProp: RelayPaginationProp,
66
64
  prevContext: RelayContext,
67
65
  contextForChildren: RelayContext,
66
+ resolverGeneration: number,
68
67
  ...
69
68
  };
70
69
 
@@ -257,7 +256,6 @@ function createGetFragmentVariables(
257
256
  'ReactRelayPaginationContainer: Unable to synthesize a ' +
258
257
  'getFragmentVariables function.',
259
258
  );
260
- // $FlowFixMe[cannot-spread-interface]
261
259
  return (prevVars: Variables, totalCount: number) => ({
262
260
  ...prevVars,
263
261
  [countVariable]: totalCount,
@@ -365,19 +363,31 @@ function createContainerWithFragments<
365
363
  this._isARequestInFlight = false;
366
364
  this._refetchSubscription = null;
367
365
  this._refetchVariables = null;
368
- this._resolver = createFragmentSpecResolver(
369
- relayContext,
370
- containerName,
371
- fragments,
372
- props,
373
- rootIsQueryRenderer,
374
- this._handleFragmentDataUpdate,
375
- );
366
+
367
+ if (RelayFeatureFlags.ENABLE_CONTAINERS_SUBSCRIBE_ON_COMMIT === true) {
368
+ this._resolver = createFragmentSpecResolver(
369
+ relayContext,
370
+ containerName,
371
+ fragments,
372
+ props,
373
+ rootIsQueryRenderer,
374
+ );
375
+ } else {
376
+ this._resolver = createFragmentSpecResolver(
377
+ relayContext,
378
+ containerName,
379
+ fragments,
380
+ props,
381
+ rootIsQueryRenderer,
382
+ this._handleFragmentDataUpdate,
383
+ );
384
+ }
376
385
  this.state = {
377
386
  data: this._resolver.resolve(),
378
387
  prevContext: relayContext,
379
388
  contextForChildren: relayContext,
380
389
  relayProp: this._buildRelayProp(relayContext),
390
+ resolverGeneration: 0,
381
391
  };
382
392
  this._isUnmounted = false;
383
393
  this._hasFetched = false;
@@ -385,6 +395,19 @@ function createContainerWithFragments<
385
395
 
386
396
  componentDidMount() {
387
397
  this._isUnmounted = false;
398
+ if (RelayFeatureFlags.ENABLE_CONTAINERS_SUBSCRIBE_ON_COMMIT === true) {
399
+ this._subscribeToNewResolverAndRerenderIfStoreHasChanged();
400
+ }
401
+ }
402
+
403
+ componentDidUpdate(prevProps: Props, prevState: ContainerState) {
404
+ if (RelayFeatureFlags.ENABLE_CONTAINERS_SUBSCRIBE_ON_COMMIT === true) {
405
+ if (prevState.resolverGeneration !== this.state.resolverGeneration) {
406
+ this._subscribeToNewResolverAndRerenderIfStoreHasChanged();
407
+ } else {
408
+ this._rerenderIfStoreHasChanged();
409
+ }
410
+ }
388
411
  }
389
412
 
390
413
  /**
@@ -418,19 +441,30 @@ function createContainerWithFragments<
418
441
  ) {
419
442
  this._cleanup();
420
443
  // Child containers rely on context.relay being mutated (for gDSFP).
421
- this._resolver = createFragmentSpecResolver(
422
- relayContext,
423
- containerName,
424
- fragments,
425
- nextProps,
426
- rootIsQueryRenderer,
427
- this._handleFragmentDataUpdate,
428
- );
429
- this.setState({
444
+ if (RelayFeatureFlags.ENABLE_CONTAINERS_SUBSCRIBE_ON_COMMIT === true) {
445
+ this._resolver = createFragmentSpecResolver(
446
+ relayContext,
447
+ containerName,
448
+ fragments,
449
+ nextProps,
450
+ rootIsQueryRenderer,
451
+ );
452
+ } else {
453
+ this._resolver = createFragmentSpecResolver(
454
+ relayContext,
455
+ containerName,
456
+ fragments,
457
+ nextProps,
458
+ rootIsQueryRenderer,
459
+ this._handleFragmentDataUpdate,
460
+ );
461
+ }
462
+ this.setState(prevState => ({
430
463
  prevContext: relayContext,
431
464
  contextForChildren: relayContext,
432
465
  relayProp: this._buildRelayProp(relayContext),
433
- });
466
+ resolverGeneration: prevState.resolverGeneration + 1,
467
+ }));
434
468
  } else if (!this._hasFetched) {
435
469
  this._resolver.setProps(nextProps);
436
470
  }
@@ -449,7 +483,8 @@ function createContainerWithFragments<
449
483
  // Short-circuit if any Relay-related data has changed
450
484
  if (
451
485
  nextState.data !== this.state.data ||
452
- nextState.relayProp !== this.state.relayProp
486
+ nextState.relayProp !== this.state.relayProp ||
487
+ nextState.resolverGeneration !== this.state.resolverGeneration
453
488
  ) {
454
489
  return true;
455
490
  }
@@ -487,6 +522,31 @@ function createContainerWithFragments<
487
522
  };
488
523
  }
489
524
 
525
+ _rerenderIfStoreHasChanged() {
526
+ const {data} = this.state;
527
+ // External values could change between render and commit.
528
+ // Check for this case, even though it requires an extra store read.
529
+ const maybeNewData = this._resolver.resolve();
530
+ if (data !== maybeNewData) {
531
+ this.setState({data: maybeNewData});
532
+ }
533
+ }
534
+
535
+ _subscribeToNewResolverAndRerenderIfStoreHasChanged() {
536
+ const {data} = this.state;
537
+ const maybeNewData = this._resolver.resolve();
538
+
539
+ // Event listeners are only safe to add during the commit phase,
540
+ // So they won't leak if render is interrupted or errors.
541
+ this._resolver.setCallback(this.props, this._handleFragmentDataUpdate);
542
+
543
+ // External values could change between render and commit.
544
+ // Check for this case, even though it requires an extra store read.
545
+ if (data !== maybeNewData) {
546
+ this.setState({data: maybeNewData});
547
+ }
548
+ }
549
+
490
550
  /**
491
551
  * Render new data for the existing props/context.
492
552
  */
@@ -703,9 +763,7 @@ function createContainerWithFragments<
703
763
  };
704
764
  let fragmentVariables;
705
765
  const rootVariables = getRootVariablesForFragments(fragments, restProps);
706
- // $FlowFixMe[cannot-spread-interface]
707
766
  fragmentVariables = getVariablesFromObject(fragments, restProps);
708
- // $FlowFixMe[cannot-spread-interface]
709
767
  fragmentVariables = {
710
768
  ...rootVariables,
711
769
  ...fragmentVariables,
@@ -726,7 +784,6 @@ function createContainerWithFragments<
726
784
  fetchVariables,
727
785
  componentName,
728
786
  );
729
- // $FlowFixMe[cannot-spread-interface]
730
787
  fetchVariables = {
731
788
  ...fetchVariables,
732
789
  ...this._refetchVariables,
@@ -843,12 +900,8 @@ function createContainerWithFragments<
843
900
  }
844
901
 
845
902
  render() {
846
- const {
847
- componentRef,
848
- __relayContext,
849
- __rootIsQueryRenderer,
850
- ...props
851
- } = this.props;
903
+ const {componentRef, __relayContext, __rootIsQueryRenderer, ...props} =
904
+ this.props;
852
905
  return (
853
906
  <ReactRelayContext.Provider value={this.state.contextForChildren}>
854
907
  <Component
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -12,14 +12,6 @@
12
12
 
13
13
  'use strict';
14
14
 
15
- const invariant = require('invariant');
16
-
17
- const {
18
- createOperationDescriptor,
19
- isRelayModernEnvironment,
20
- __internal: {fetchQuery},
21
- } = require('relay-runtime');
22
-
23
15
  import type {
24
16
  CacheConfig,
25
17
  Disposable,
@@ -29,6 +21,13 @@ import type {
29
21
  Snapshot,
30
22
  } from 'relay-runtime';
31
23
 
24
+ const invariant = require('invariant');
25
+ const {
26
+ __internal: {fetchQuery},
27
+ createOperationDescriptor,
28
+ isRelayModernEnvironment,
29
+ } = require('relay-runtime');
30
+
32
31
  type OnDataChange = ({
33
32
  error?: Error,
34
33
  snapshot?: Snapshot,
@@ -341,8 +340,8 @@ class ReactRelayQueryFetcher {
341
340
  this._rootSubscription = environment.subscribe(this._snapshot, snapshot => {
342
341
  // Read from this._fetchOptions in case onDataChange() was lazily added.
343
342
  if (this._fetchOptions != null) {
344
- const maybeNewOnDataChangeCallbacks = this._fetchOptions
345
- .onDataChangeCallbacks;
343
+ const maybeNewOnDataChangeCallbacks =
344
+ this._fetchOptions.onDataChangeCallbacks;
346
345
  if (Array.isArray(maybeNewOnDataChangeCallbacks)) {
347
346
  maybeNewOnDataChangeCallbacks.forEach(onDataChange =>
348
347
  onDataChange({snapshot}),