react-relay 11.0.0 → 13.0.0-rc.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. package/ReactRelayContext.js +1 -1
  2. package/ReactRelayContext.js.flow +2 -3
  3. package/ReactRelayFragmentContainer.js.flow +24 -24
  4. package/ReactRelayFragmentMockRenderer.js.flow +1 -1
  5. package/ReactRelayLocalQueryRenderer.js.flow +7 -8
  6. package/ReactRelayPaginationContainer.js.flow +111 -54
  7. package/ReactRelayQueryFetcher.js.flow +9 -10
  8. package/ReactRelayQueryRenderer.js.flow +115 -81
  9. package/ReactRelayRefetchContainer.js.flow +40 -35
  10. package/ReactRelayTestMocker.js.flow +16 -12
  11. package/ReactRelayTypes.js.flow +10 -10
  12. package/RelayContext.js.flow +3 -3
  13. package/__flowtests__/ReactRelayFragmentContainer-flowtest.js.flow +1 -2
  14. package/__flowtests__/ReactRelayPaginationContainer-flowtest.js.flow +12 -7
  15. package/__flowtests__/ReactRelayRefetchContainer-flowtest.js.flow +10 -6
  16. package/__flowtests__/RelayModern-flowtest.js.flow +78 -46
  17. package/__flowtests__/RelayModernFlowtest_badref.graphql.js.flow +5 -4
  18. package/__flowtests__/RelayModernFlowtest_notref.graphql.js.flow +5 -4
  19. package/__flowtests__/RelayModernFlowtest_user.graphql.js.flow +4 -3
  20. package/__flowtests__/RelayModernFlowtest_users.graphql.js.flow +4 -3
  21. package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer.graphql.js.flow +72 -0
  22. package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer2.graphql.js.flow +72 -0
  23. package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtestQuery.graphql.js.flow +227 -0
  24. package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtest_viewer.graphql.js.flow +164 -0
  25. package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtestQuery.graphql.js.flow +227 -0
  26. package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtest_viewer.graphql.js.flow +164 -0
  27. package/__flowtests__/__generated__/RelayModernFlowtest_badref.graphql.js.flow +66 -0
  28. package/__flowtests__/__generated__/RelayModernFlowtest_notref.graphql.js.flow +66 -0
  29. package/__flowtests__/__generated__/RelayModernFlowtest_user.graphql.js.flow +59 -0
  30. package/__flowtests__/__generated__/RelayModernFlowtest_users.graphql.js.flow +61 -0
  31. package/assertFragmentMap.js.flow +2 -2
  32. package/buildReactRelayContainer.js.flow +15 -12
  33. package/getRootVariablesForFragments.js.flow +2 -3
  34. package/hooks.js +1 -1
  35. package/hooks.js.flow +5 -6
  36. package/index.js +1 -1
  37. package/index.js.flow +6 -7
  38. package/jest-react/enqueueTask.js.flow +56 -0
  39. package/jest-react/index.js.flow +12 -0
  40. package/jest-react/internalAct.js.flow +139 -0
  41. package/legacy.js +1 -1
  42. package/lib/ReactRelayFragmentContainer.js +21 -15
  43. package/lib/ReactRelayFragmentMockRenderer.js +2 -2
  44. package/lib/ReactRelayLocalQueryRenderer.js +7 -8
  45. package/lib/ReactRelayPaginationContainer.js +92 -30
  46. package/lib/ReactRelayQueryFetcher.js +3 -3
  47. package/lib/ReactRelayQueryRenderer.js +86 -53
  48. package/lib/ReactRelayRefetchContainer.js +36 -21
  49. package/lib/ReactRelayTestMocker.js +7 -6
  50. package/lib/RelayContext.js +3 -2
  51. package/lib/assertFragmentMap.js +3 -2
  52. package/lib/buildReactRelayContainer.js +14 -11
  53. package/lib/hooks.js +5 -5
  54. package/lib/index.js +7 -7
  55. package/lib/jest-react/enqueueTask.js +53 -0
  56. package/lib/jest-react/index.js +13 -0
  57. package/lib/jest-react/internalAct.js +116 -0
  58. package/lib/multi-actor/ActorChange.js +30 -0
  59. package/lib/multi-actor/index.js +11 -0
  60. package/lib/multi-actor/useRelayActorEnvironment.js +29 -0
  61. package/lib/relay-hooks/EntryPointContainer.react.js +3 -3
  62. package/lib/relay-hooks/FragmentResource.js +351 -94
  63. package/lib/relay-hooks/LRUCache.js +1 -1
  64. package/lib/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js +4 -4
  65. package/lib/relay-hooks/MatchContainer.js +1 -1
  66. package/lib/relay-hooks/QueryResource.js +172 -29
  67. package/lib/relay-hooks/RelayEnvironmentProvider.js +5 -3
  68. package/lib/relay-hooks/SuspenseResource.js +130 -0
  69. package/lib/relay-hooks/loadQuery.js +42 -20
  70. package/lib/relay-hooks/preloadQuery_DEPRECATED.js +24 -15
  71. package/lib/relay-hooks/useBlockingPaginationFragment.js +4 -5
  72. package/lib/relay-hooks/useEntryPointLoader.js +2 -2
  73. package/lib/relay-hooks/useFetchTrackingRef.js +2 -1
  74. package/lib/relay-hooks/useFragment.js +8 -7
  75. package/lib/relay-hooks/useFragmentNode.js +4 -4
  76. package/lib/relay-hooks/useIsOperationNodeActive.js +3 -3
  77. package/lib/relay-hooks/useLazyLoadQuery.js +3 -3
  78. package/lib/relay-hooks/useLazyLoadQueryNode.js +10 -4
  79. package/lib/relay-hooks/useLoadMoreFunction.js +6 -8
  80. package/lib/relay-hooks/useMemoOperationDescriptor.js +2 -2
  81. package/lib/relay-hooks/useMemoVariables.js +2 -2
  82. package/lib/relay-hooks/useMutation.js +17 -6
  83. package/lib/relay-hooks/usePaginationFragment.js +2 -3
  84. package/lib/relay-hooks/usePreloadedQuery.js +8 -7
  85. package/lib/relay-hooks/useQueryLoader.js +30 -10
  86. package/lib/relay-hooks/useRefetchableFragmentNode.js +12 -14
  87. package/lib/relay-hooks/useRelayEnvironment.js +3 -3
  88. package/lib/relay-hooks/useStaticFragmentNodeWarning.js +2 -2
  89. package/lib/relay-hooks/useSubscribeToInvalidationState.js +2 -1
  90. package/lib/relay-hooks/useSubscription.js +10 -7
  91. package/multi-actor/ActorChange.js.flow +58 -0
  92. package/multi-actor/index.js.flow +14 -0
  93. package/multi-actor/useRelayActorEnvironment.js.flow +49 -0
  94. package/package.json +3 -2
  95. package/react-relay-hooks.js +2 -2
  96. package/react-relay-hooks.min.js +2 -2
  97. package/react-relay-legacy.js +2 -2
  98. package/react-relay-legacy.min.js +2 -2
  99. package/react-relay.js +2 -2
  100. package/react-relay.min.js +2 -2
  101. package/relay-hooks/EntryPointContainer.react.js.flow +8 -15
  102. package/relay-hooks/EntryPointTypes.flow.js.flow +24 -25
  103. package/relay-hooks/FragmentResource.js.flow +376 -95
  104. package/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js.flow +32 -46
  105. package/relay-hooks/MatchContainer.js.flow +3 -2
  106. package/relay-hooks/QueryResource.js.flow +216 -25
  107. package/relay-hooks/RelayEnvironmentProvider.js.flow +14 -4
  108. package/relay-hooks/SuspenseResource.js.flow +115 -0
  109. package/relay-hooks/__flowtests__/EntryPointTypes/EntryPointElementConfig-flowtest.js.flow +4 -3
  110. package/relay-hooks/__flowtests__/EntryPointTypes/NestedEntrypoints-flowtest.js.flow +1 -1
  111. package/relay-hooks/__flowtests__/useBlockingPaginationFragment-flowtest.js.flow +10 -9
  112. package/relay-hooks/__flowtests__/useFragment-flowtest.js.flow +8 -7
  113. package/relay-hooks/__flowtests__/usePaginationFragment-flowtest.js.flow +10 -9
  114. package/relay-hooks/__flowtests__/useRefetchableFragment-flowtest.js.flow +10 -9
  115. package/relay-hooks/__flowtests__/utils.js.flow +8 -12
  116. package/relay-hooks/loadEntryPoint.js.flow +6 -12
  117. package/relay-hooks/loadQuery.js.flow +49 -31
  118. package/relay-hooks/preloadQuery_DEPRECATED.js.flow +30 -21
  119. package/relay-hooks/prepareEntryPoint_DEPRECATED.js.flow +6 -12
  120. package/relay-hooks/useBlockingPaginationFragment.js.flow +13 -11
  121. package/relay-hooks/useEntryPointLoader.js.flow +7 -10
  122. package/relay-hooks/useFetchTrackingRef.js.flow +2 -2
  123. package/relay-hooks/useFragment.js.flow +26 -46
  124. package/relay-hooks/useFragmentNode.js.flow +5 -7
  125. package/relay-hooks/useIsOperationNodeActive.js.flow +3 -5
  126. package/relay-hooks/useIsParentQueryActive.js.flow +3 -4
  127. package/relay-hooks/useLazyLoadQuery.js.flow +9 -10
  128. package/relay-hooks/useLazyLoadQueryNode.js.flow +19 -13
  129. package/relay-hooks/useLoadMoreFunction.js.flow +20 -27
  130. package/relay-hooks/useMemoOperationDescriptor.js.flow +5 -7
  131. package/relay-hooks/useMemoVariables.js.flow +6 -6
  132. package/relay-hooks/useMutation.js.flow +26 -26
  133. package/relay-hooks/usePaginationFragment.js.flow +38 -44
  134. package/relay-hooks/usePreloadedQuery.js.flow +18 -14
  135. package/relay-hooks/useQueryLoader.js.flow +41 -22
  136. package/relay-hooks/useRefetchableFragment.js.flow +7 -8
  137. package/relay-hooks/useRefetchableFragmentNode.js.flow +24 -30
  138. package/relay-hooks/useRelayEnvironment.js.flow +2 -4
  139. package/relay-hooks/useStaticFragmentNodeWarning.js.flow +2 -3
  140. package/relay-hooks/useSubscribeToInvalidationState.js.flow +3 -6
  141. package/relay-hooks/useSubscription.js.flow +20 -10
  142. package/lib/relay-hooks/getPaginationMetadata.js +0 -41
  143. package/lib/relay-hooks/getPaginationVariables.js +0 -66
  144. package/lib/relay-hooks/getRefetchMetadata.js +0 -36
  145. package/lib/relay-hooks/getValueAtPath.js +0 -51
  146. package/relay-hooks/getPaginationMetadata.js.flow +0 -74
  147. package/relay-hooks/getPaginationVariables.js.flow +0 -108
  148. package/relay-hooks/getRefetchMetadata.js.flow +0 -80
  149. package/relay-hooks/getValueAtPath.js.flow +0 -46
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Relay v11.0.0
2
+ * Relay v13.0.0-rc.0
3
3
  *
4
4
  * Copyright (c) Facebook, Inc. and its affiliates.
5
5
  *
@@ -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>);
@@ -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,
@@ -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 (
@@ -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,
@@ -41,7 +40,7 @@ const queryRendererContext: ReactRelayQueryRendererContextType = {
41
40
  rootIsQueryRenderer: true,
42
41
  };
43
42
 
44
- function useDeepCompare<T: {...}>(value: T): T {
43
+ function useDeepCompare<T: interface {}>(value: T): T {
45
44
  const latestValue = React.useRef(value);
46
45
  if (!areEqual(latestValue.current, value)) {
47
46
  if (__DEV__) {
@@ -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
 
@@ -364,19 +363,31 @@ function createContainerWithFragments<
364
363
  this._isARequestInFlight = false;
365
364
  this._refetchSubscription = null;
366
365
  this._refetchVariables = null;
367
- this._resolver = createFragmentSpecResolver(
368
- relayContext,
369
- containerName,
370
- fragments,
371
- props,
372
- rootIsQueryRenderer,
373
- this._handleFragmentDataUpdate,
374
- );
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
+ }
375
385
  this.state = {
376
386
  data: this._resolver.resolve(),
377
387
  prevContext: relayContext,
378
388
  contextForChildren: relayContext,
379
389
  relayProp: this._buildRelayProp(relayContext),
390
+ resolverGeneration: 0,
380
391
  };
381
392
  this._isUnmounted = false;
382
393
  this._hasFetched = false;
@@ -384,6 +395,19 @@ function createContainerWithFragments<
384
395
 
385
396
  componentDidMount() {
386
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
+ }
387
411
  }
388
412
 
389
413
  /**
@@ -417,19 +441,30 @@ function createContainerWithFragments<
417
441
  ) {
418
442
  this._cleanup();
419
443
  // Child containers rely on context.relay being mutated (for gDSFP).
420
- this._resolver = createFragmentSpecResolver(
421
- relayContext,
422
- containerName,
423
- fragments,
424
- nextProps,
425
- rootIsQueryRenderer,
426
- this._handleFragmentDataUpdate,
427
- );
428
- 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 => ({
429
463
  prevContext: relayContext,
430
464
  contextForChildren: relayContext,
431
465
  relayProp: this._buildRelayProp(relayContext),
432
- });
466
+ resolverGeneration: prevState.resolverGeneration + 1,
467
+ }));
433
468
  } else if (!this._hasFetched) {
434
469
  this._resolver.setProps(nextProps);
435
470
  }
@@ -448,7 +483,8 @@ function createContainerWithFragments<
448
483
  // Short-circuit if any Relay-related data has changed
449
484
  if (
450
485
  nextState.data !== this.state.data ||
451
- nextState.relayProp !== this.state.relayProp
486
+ nextState.relayProp !== this.state.relayProp ||
487
+ nextState.resolverGeneration !== this.state.resolverGeneration
452
488
  ) {
453
489
  return true;
454
490
  }
@@ -486,6 +522,31 @@ function createContainerWithFragments<
486
522
  };
487
523
  }
488
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
+
489
550
  /**
490
551
  * Render new data for the existing props/context.
491
552
  */
@@ -839,12 +900,8 @@ function createContainerWithFragments<
839
900
  }
840
901
 
841
902
  render() {
842
- const {
843
- componentRef,
844
- __relayContext,
845
- __rootIsQueryRenderer,
846
- ...props
847
- } = this.props;
903
+ const {componentRef, __relayContext, __rootIsQueryRenderer, ...props} =
904
+ this.props;
848
905
  return (
849
906
  <ReactRelayContext.Provider value={this.state.contextForChildren}>
850
907
  <Component
@@ -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}),