react-relay 11.0.0 → 13.0.0-rc.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 (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}),