react-relay 11.0.2 → 13.0.0-rc.2

Sign up to get free protection for your applications and to get access to all the features.
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}),