react-relay 14.0.0 → 14.1.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 (163) hide show
  1. package/ReactRelayContainerUtils.js.flow +0 -2
  2. package/ReactRelayContext.js +1 -1
  3. package/ReactRelayContext.js.flow +0 -2
  4. package/ReactRelayFragmentContainer.js.flow +0 -2
  5. package/ReactRelayFragmentMockRenderer.js.flow +0 -2
  6. package/ReactRelayLocalQueryRenderer.js.flow +0 -2
  7. package/ReactRelayPaginationContainer.js.flow +0 -2
  8. package/ReactRelayQueryFetcher.js.flow +9 -11
  9. package/ReactRelayQueryRenderer.js.flow +10 -12
  10. package/ReactRelayQueryRendererContext.js.flow +1 -3
  11. package/ReactRelayRefetchContainer.js.flow +0 -4
  12. package/ReactRelayTestMocker.js.flow +0 -2
  13. package/ReactRelayTypes.js.flow +6 -8
  14. package/RelayContext.js.flow +0 -2
  15. package/__flowtests__/ReactRelayFragmentContainer-flowtest.js.flow +2 -4
  16. package/__flowtests__/ReactRelayPaginationContainer-flowtest.js.flow +3 -5
  17. package/__flowtests__/ReactRelayRefetchContainer-flowtest.js.flow +3 -5
  18. package/__flowtests__/RelayModern-flowtest.js.flow +2 -4
  19. package/__flowtests__/RelayModernFlowtest_badref.graphql.js.flow +2 -4
  20. package/__flowtests__/RelayModernFlowtest_notref.graphql.js.flow +2 -4
  21. package/__flowtests__/RelayModernFlowtest_user.graphql.js.flow +2 -4
  22. package/__flowtests__/RelayModernFlowtest_users.graphql.js.flow +2 -4
  23. package/assertFragmentMap.js.flow +0 -2
  24. package/buildReactRelayContainer.js.flow +0 -2
  25. package/getRootVariablesForFragments.js.flow +0 -2
  26. package/hooks.js +1 -1
  27. package/hooks.js.flow +0 -2
  28. package/index.js +1 -1
  29. package/index.js.flow +2 -2
  30. package/isRelayEnvironment.js.flow +0 -2
  31. package/legacy.js +1 -1
  32. package/legacy.js.flow +0 -2
  33. package/lib/ReactRelayContainerUtils.js +0 -1
  34. package/lib/ReactRelayContext.js +0 -1
  35. package/lib/ReactRelayFragmentContainer.js +10 -9
  36. package/lib/ReactRelayFragmentMockRenderer.js +0 -1
  37. package/lib/ReactRelayLocalQueryRenderer.js +0 -1
  38. package/lib/ReactRelayPaginationContainer.js +14 -11
  39. package/lib/ReactRelayQueryFetcher.js +1 -2
  40. package/lib/ReactRelayQueryRenderer.js +1 -2
  41. package/lib/ReactRelayQueryRendererContext.js +0 -1
  42. package/lib/ReactRelayRefetchContainer.js +11 -14
  43. package/lib/ReactRelayTestMocker.js +1 -2
  44. package/lib/ReactRelayTypes.js +0 -1
  45. package/lib/RelayContext.js +0 -1
  46. package/lib/assertFragmentMap.js +0 -1
  47. package/lib/buildReactRelayContainer.js +1 -2
  48. package/lib/getRootVariablesForFragments.js +1 -2
  49. package/lib/hooks.js +0 -1
  50. package/lib/index.js +3 -1
  51. package/lib/isRelayEnvironment.js +0 -1
  52. package/lib/legacy.js +0 -1
  53. package/lib/multi-actor/useRelayActorEnvironment.js +0 -1
  54. package/lib/readContext.js +0 -1
  55. package/lib/relay-hooks/EntryPointContainer.react.js +0 -1
  56. package/lib/relay-hooks/EntryPointTypes.flow.js +0 -1
  57. package/lib/relay-hooks/FragmentResource.js +7 -7
  58. package/lib/relay-hooks/HooksImplementation.js +1 -1
  59. package/lib/relay-hooks/InternalLogger.js +0 -1
  60. package/lib/relay-hooks/LRUCache.js +0 -1
  61. package/lib/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js +0 -1
  62. package/lib/relay-hooks/MatchContainer.js +1 -2
  63. package/lib/relay-hooks/ProfilerContext.js +0 -1
  64. package/lib/relay-hooks/QueryResource.js +1 -2
  65. package/lib/relay-hooks/RelayEnvironmentProvider.js +0 -1
  66. package/lib/relay-hooks/SuspenseResource.js +1 -2
  67. package/lib/relay-hooks/loadQuery.js +1 -1
  68. package/lib/relay-hooks/preloadQuery_DEPRECATED.js +1 -2
  69. package/lib/relay-hooks/prepareEntryPoint_DEPRECATED.js +0 -1
  70. package/lib/relay-hooks/react-cache/RelayReactCache.js +0 -1
  71. package/lib/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js +3 -3
  72. package/lib/relay-hooks/react-cache/readFragmentInternal_REACT_CACHE.js +239 -0
  73. package/lib/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js +183 -125
  74. package/lib/relay-hooks/react-cache/useFragment_REACT_CACHE.js +0 -1
  75. package/lib/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js +0 -1
  76. package/lib/relay-hooks/react-cache/usePaginationFragment_REACT_CACHE.js +150 -0
  77. package/lib/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js +0 -1
  78. package/lib/relay-hooks/react-cache/useRefetchableFragmentInternal_REACT_CACHE.js +367 -0
  79. package/lib/relay-hooks/react-cache/useRefetchableFragment_REACT_CACHE.js +45 -0
  80. package/lib/relay-hooks/useBlockingPaginationFragment.js +4 -3
  81. package/lib/relay-hooks/useClientQuery.js +33 -0
  82. package/lib/relay-hooks/useEntryPointLoader.js +1 -2
  83. package/lib/relay-hooks/useFetchTrackingRef.js +0 -1
  84. package/lib/relay-hooks/useFragment.js +0 -1
  85. package/lib/relay-hooks/useFragmentNode.js +0 -1
  86. package/lib/relay-hooks/useIsMountedRef.js +0 -1
  87. package/lib/relay-hooks/useLazyLoadQuery.js +1 -15
  88. package/lib/relay-hooks/useLazyLoadQueryNode.js +0 -1
  89. package/lib/relay-hooks/useLoadMoreFunction.js +1 -2
  90. package/lib/relay-hooks/useMemoOperationDescriptor.js +0 -1
  91. package/lib/relay-hooks/useMemoVariables.js +0 -1
  92. package/lib/relay-hooks/useMutation.js +1 -2
  93. package/lib/relay-hooks/usePaginationFragment.js +15 -3
  94. package/lib/relay-hooks/usePreloadedQuery.js +1 -15
  95. package/lib/relay-hooks/useQueryLoader.js +1 -2
  96. package/lib/relay-hooks/useRefetchableFragment.js +14 -2
  97. package/lib/relay-hooks/useRefetchableFragmentNode.js +1 -2
  98. package/lib/relay-hooks/useRelayEnvironment.js +0 -1
  99. package/lib/relay-hooks/useStaticFragmentNodeWarning.js +0 -1
  100. package/lib/relay-hooks/useSubscribeToInvalidationState.js +0 -1
  101. package/lib/relay-hooks/useSubscription.js +0 -1
  102. package/multi-actor/useRelayActorEnvironment.js.flow +0 -2
  103. package/package.json +2 -2
  104. package/react-relay-hooks.js +2 -2
  105. package/react-relay-hooks.min.js +2 -2
  106. package/react-relay-legacy.js +2 -2
  107. package/react-relay-legacy.min.js +2 -2
  108. package/react-relay.js +2 -2
  109. package/react-relay.min.js +2 -2
  110. package/readContext.js.flow +0 -2
  111. package/relay-hooks/EntryPointContainer.react.js.flow +2 -4
  112. package/relay-hooks/EntryPointTypes.flow.js.flow +30 -32
  113. package/relay-hooks/FragmentResource.js.flow +9 -11
  114. package/relay-hooks/HooksImplementation.js.flow +6 -8
  115. package/relay-hooks/InternalLogger.js.flow +0 -2
  116. package/relay-hooks/LRUCache.js.flow +0 -2
  117. package/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js.flow +4 -6
  118. package/relay-hooks/MatchContainer.js.flow +5 -7
  119. package/relay-hooks/ProfilerContext.js.flow +0 -2
  120. package/relay-hooks/QueryResource.js.flow +4 -6
  121. package/relay-hooks/RelayEnvironmentProvider.js.flow +2 -4
  122. package/relay-hooks/SuspenseResource.js.flow +0 -2
  123. package/relay-hooks/__flowtests__/EntryPointTypes/EntryPointElementConfig-flowtest.js.flow +3 -3
  124. package/relay-hooks/__flowtests__/EntryPointTypes/NestedEntrypoints-flowtest.js.flow +2 -2
  125. package/relay-hooks/__flowtests__/useBlockingPaginationFragment-flowtest.js.flow +4 -6
  126. package/relay-hooks/__flowtests__/useFragment-flowtest.js.flow +0 -2
  127. package/relay-hooks/__flowtests__/usePaginationFragment-flowtest.js.flow +4 -6
  128. package/relay-hooks/__flowtests__/useRefetchableFragment-flowtest.js.flow +0 -2
  129. package/relay-hooks/__flowtests__/utils.js.flow +8 -10
  130. package/relay-hooks/preloadQuery_DEPRECATED.js.flow +4 -6
  131. package/relay-hooks/prepareEntryPoint_DEPRECATED.js.flow +0 -2
  132. package/relay-hooks/react-cache/RelayReactCache.js.flow +0 -2
  133. package/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js.flow +22 -16
  134. package/relay-hooks/react-cache/readFragmentInternal_REACT_CACHE.js.flow +297 -0
  135. package/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js.flow +134 -94
  136. package/relay-hooks/react-cache/useFragment_REACT_CACHE.js.flow +0 -2
  137. package/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js.flow +2 -4
  138. package/relay-hooks/react-cache/usePaginationFragment_REACT_CACHE.js.flow +171 -0
  139. package/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js.flow +2 -4
  140. package/relay-hooks/react-cache/useRefetchableFragmentInternal_REACT_CACHE.js.flow +595 -0
  141. package/relay-hooks/react-cache/useRefetchableFragment_REACT_CACHE.js.flow +65 -0
  142. package/relay-hooks/useBlockingPaginationFragment.js.flow +4 -6
  143. package/relay-hooks/useClientQuery.js.flow +39 -0
  144. package/relay-hooks/useEntryPointLoader.js.flow +6 -8
  145. package/relay-hooks/useFetchTrackingRef.js.flow +2 -4
  146. package/relay-hooks/useFragment.js.flow +0 -2
  147. package/relay-hooks/useFragmentNode.js.flow +2 -4
  148. package/relay-hooks/useIsMountedRef.js.flow +1 -3
  149. package/relay-hooks/useLazyLoadQuery.js.flow +7 -30
  150. package/relay-hooks/useLazyLoadQueryNode.js.flow +2 -4
  151. package/relay-hooks/useLoadMoreFunction.js.flow +6 -8
  152. package/relay-hooks/useMemoOperationDescriptor.js.flow +0 -2
  153. package/relay-hooks/useMemoVariables.js.flow +0 -2
  154. package/relay-hooks/useMutation.js.flow +2 -4
  155. package/relay-hooks/usePaginationFragment.js.flow +44 -19
  156. package/relay-hooks/usePreloadedQuery.js.flow +5 -24
  157. package/relay-hooks/useQueryLoader.js.flow +4 -6
  158. package/relay-hooks/useRefetchableFragment.js.flow +32 -3
  159. package/relay-hooks/useRefetchableFragmentNode.js.flow +16 -18
  160. package/relay-hooks/useRelayEnvironment.js.flow +0 -2
  161. package/relay-hooks/useStaticFragmentNodeWarning.js.flow +0 -2
  162. package/relay-hooks/useSubscribeToInvalidationState.js.flow +0 -2
  163. package/relay-hooks/useSubscription.js.flow +0 -2
@@ -8,10 +8,9 @@
8
8
  * @emails oncall+relay
9
9
  * @format
10
10
  */
11
- // flowlint ambiguous-object-type:error
12
11
  'use strict';
13
12
 
14
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
13
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
15
14
 
16
15
  var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
17
16
 
@@ -19,27 +18,29 @@ var _createForOfIteratorHelper2 = _interopRequireDefault(require("@babel/runtime
19
18
 
20
19
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
21
20
 
22
- var useRelayEnvironment = require('../useRelayEnvironment');
21
+ var _require = require('../QueryResource'),
22
+ getQueryResourceForEnvironment = _require.getQueryResourceForEnvironment;
23
23
 
24
- var getQueryResultOrFetchQuery = require('./getQueryResultOrFetchQuery_REACT_CACHE');
24
+ var useRelayEnvironment = require('../useRelayEnvironment');
25
25
 
26
26
  var invariant = require('invariant');
27
27
 
28
- var _require = require('react'),
29
- useDebugValue = _require.useDebugValue,
30
- useEffect = _require.useEffect,
31
- useMemo = _require.useMemo,
32
- useRef = _require.useRef,
33
- useState = _require.useState;
34
-
35
- var _require2 = require('relay-runtime'),
36
- areEqualSelectors = _require2.areEqualSelectors,
37
- createOperationDescriptor = _require2.createOperationDescriptor,
38
- getPendingOperationsForFragment = _require2.getPendingOperationsForFragment,
39
- getSelector = _require2.getSelector,
40
- getVariablesFromFragment = _require2.getVariablesFromFragment,
41
- handlePotentialSnapshotErrors = _require2.handlePotentialSnapshotErrors,
42
- recycleNodesInto = _require2.recycleNodesInto;
28
+ var _require2 = require('react'),
29
+ useDebugValue = _require2.useDebugValue,
30
+ useEffect = _require2.useEffect,
31
+ useMemo = _require2.useMemo,
32
+ useRef = _require2.useRef,
33
+ useState = _require2.useState;
34
+
35
+ var _require3 = require('relay-runtime'),
36
+ fetchQueryInternal = _require3.__internal.fetchQuery,
37
+ areEqualSelectors = _require3.areEqualSelectors,
38
+ createOperationDescriptor = _require3.createOperationDescriptor,
39
+ getPendingOperationsForFragment = _require3.getPendingOperationsForFragment,
40
+ getSelector = _require3.getSelector,
41
+ getVariablesFromFragment = _require3.getVariablesFromFragment,
42
+ handlePotentialSnapshotErrors = _require3.handlePotentialSnapshotErrors,
43
+ recycleNodesInto = _require3.recycleNodesInto;
43
44
 
44
45
  var warning = require("fbjs/lib/warning");
45
46
 
@@ -102,23 +103,70 @@ function getMissingClientEdges(state) {
102
103
  }
103
104
  }
104
105
 
105
- function handlePotentialSnapshotErrorsForState(environment, state) {
106
- if (state.kind === 'singular') {
107
- handlePotentialSnapshotErrors(environment, state.snapshot.missingRequiredFields, state.snapshot.relayResolverErrors);
108
- } else if (state.kind === 'plural') {
106
+ function getSuspendingLiveResolver(state) {
107
+ if (state.kind === 'bailout') {
108
+ return null;
109
+ } else if (state.kind === 'singular') {
110
+ var _state$snapshot$missi2;
111
+
112
+ return (_state$snapshot$missi2 = state.snapshot.missingLiveResolverFields) !== null && _state$snapshot$missi2 !== void 0 ? _state$snapshot$missi2 : null;
113
+ } else {
114
+ var missingFields = null;
115
+
109
116
  var _iterator3 = (0, _createForOfIteratorHelper2["default"])(state.snapshots),
110
117
  _step3;
111
118
 
112
119
  try {
113
120
  for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
114
121
  var snapshot = _step3.value;
115
- handlePotentialSnapshotErrors(environment, snapshot.missingRequiredFields, snapshot.relayResolverErrors);
122
+
123
+ if (snapshot.missingLiveResolverFields) {
124
+ var _missingFields;
125
+
126
+ missingFields = (_missingFields = missingFields) !== null && _missingFields !== void 0 ? _missingFields : [];
127
+
128
+ var _iterator4 = (0, _createForOfIteratorHelper2["default"])(snapshot.missingLiveResolverFields),
129
+ _step4;
130
+
131
+ try {
132
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
133
+ var edge = _step4.value;
134
+ missingFields.push(edge);
135
+ }
136
+ } catch (err) {
137
+ _iterator4.e(err);
138
+ } finally {
139
+ _iterator4.f();
140
+ }
141
+ }
116
142
  }
117
143
  } catch (err) {
118
144
  _iterator3.e(err);
119
145
  } finally {
120
146
  _iterator3.f();
121
147
  }
148
+
149
+ return missingFields;
150
+ }
151
+ }
152
+
153
+ function handlePotentialSnapshotErrorsForState(environment, state) {
154
+ if (state.kind === 'singular') {
155
+ handlePotentialSnapshotErrors(environment, state.snapshot.missingRequiredFields, state.snapshot.relayResolverErrors);
156
+ } else if (state.kind === 'plural') {
157
+ var _iterator5 = (0, _createForOfIteratorHelper2["default"])(state.snapshots),
158
+ _step5;
159
+
160
+ try {
161
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
162
+ var snapshot = _step5.value;
163
+ handlePotentialSnapshotErrors(environment, snapshot.missingRequiredFields, snapshot.relayResolverErrors);
164
+ }
165
+ } catch (err) {
166
+ _iterator5.e(err);
167
+ } finally {
168
+ _iterator5.f();
169
+ }
122
170
  }
123
171
  }
124
172
  /**
@@ -205,16 +253,11 @@ function handleMissingClientEdge(environment, parentFragmentNode, parentFragment
205
253
  });
206
254
  var queryOperationDescriptor = createOperationDescriptor(missingClientEdgeRequestInfo.request, variables, queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.networkCacheConfig); // This may suspend. We don't need to do anything with the results; all we're
207
255
  // doing here is started the query if needed and retaining and releasing it
208
- // according to the component mount/suspense cycle; getQueryResultOrFetchQuery
256
+ // according to the component mount/suspense cycle; QueryResource
209
257
  // already handles this by itself.
210
258
 
211
- var _getQueryResultOrFetc = getQueryResultOrFetchQuery(environment, queryOperationDescriptor, {
212
- fetchPolicy: queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.fetchPolicy
213
- }),
214
- _ = _getQueryResultOrFetc[0],
215
- effect = _getQueryResultOrFetc[1];
216
-
217
- return effect;
259
+ var QueryResource = getQueryResourceForEnvironment(environment);
260
+ return QueryResource.prepare(queryOperationDescriptor, fetchQueryInternal(environment, queryOperationDescriptor), queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.fetchPolicy);
218
261
  }
219
262
 
220
263
  function subscribeToSnapshot(environment, state, setState) {
@@ -222,7 +265,14 @@ function subscribeToSnapshot(environment, state, setState) {
222
265
  return function () {};
223
266
  } else if (state.kind === 'singular') {
224
267
  var disposable = environment.subscribe(state.snapshot, function (latestSnapshot) {
225
- setState(function (_) {
268
+ setState(function (prevState) {
269
+ // In theory a setState from a subscription could be batched together
270
+ // with a setState to change the fragment selector. Guard against this
271
+ // by bailing out of the state update if the selector has changed.
272
+ if (prevState.kind !== 'singular' || prevState.snapshot.selector !== latestSnapshot.selector) {
273
+ return prevState;
274
+ }
275
+
226
276
  return {
227
277
  kind: 'singular',
228
278
  snapshot: latestSnapshot,
@@ -236,9 +286,17 @@ function subscribeToSnapshot(environment, state, setState) {
236
286
  } else {
237
287
  var disposables = state.snapshots.map(function (snapshot, index) {
238
288
  return environment.subscribe(snapshot, function (latestSnapshot) {
239
- setState(function (existing) {
240
- !(existing.kind === 'plural') ? process.env.NODE_ENV !== "production" ? invariant(false, 'Cannot go from singular to plural or from bailout to plural.') : invariant(false) : void 0;
241
- var updated = (0, _toConsumableArray2["default"])(existing.snapshots);
289
+ setState(function (prevState) {
290
+ var _prevState$snapshots$;
291
+
292
+ // In theory a setState from a subscription could be batched together
293
+ // with a setState to change the fragment selector. Guard against this
294
+ // by bailing out of the state update if the selector has changed.
295
+ if (prevState.kind !== 'plural' || ((_prevState$snapshots$ = prevState.snapshots[index]) === null || _prevState$snapshots$ === void 0 ? void 0 : _prevState$snapshots$.selector) !== latestSnapshot.selector) {
296
+ return prevState;
297
+ }
298
+
299
+ var updated = (0, _toConsumableArray2["default"])(prevState.snapshots);
242
300
  updated[index] = latestSnapshot;
243
301
  return {
244
302
  kind: 'plural',
@@ -249,29 +307,31 @@ function subscribeToSnapshot(environment, state, setState) {
249
307
  });
250
308
  });
251
309
  return function () {
252
- var _iterator4 = (0, _createForOfIteratorHelper2["default"])(disposables),
253
- _step4;
310
+ var _iterator6 = (0, _createForOfIteratorHelper2["default"])(disposables),
311
+ _step6;
254
312
 
255
313
  try {
256
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
257
- var d = _step4.value;
314
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
315
+ var d = _step6.value;
258
316
  d.dispose();
259
317
  }
260
318
  } catch (err) {
261
- _iterator4.e(err);
319
+ _iterator6.e(err);
262
320
  } finally {
263
- _iterator4.f();
321
+ _iterator6.f();
264
322
  }
265
323
  };
266
324
  }
267
325
  }
268
326
 
269
- function getFragmentState(environment, fragmentSelector, isPlural) {
327
+ function getFragmentState(environment, fragmentSelector) {
270
328
  if (fragmentSelector == null) {
271
329
  return {
272
330
  kind: 'bailout'
273
331
  };
274
332
  } else if (fragmentSelector.kind === 'PluralReaderSelector') {
333
+ // Note that if fragmentRef is an empty array, fragmentSelector will be null so we'll hit the above case.
334
+ // Null is returned by getSelector if fragmentRef has no non-null items.
275
335
  return {
276
336
  kind: 'plural',
277
337
  snapshots: fragmentSelector.selectors.map(function (s) {
@@ -307,38 +367,21 @@ function useFragmentInternal_REACT_CACHE(fragmentNode, fragmentRef, hookDisplayN
307
367
  var environment = useRelayEnvironment();
308
368
 
309
369
  var _useState = useState(function () {
310
- return getFragmentState(environment, fragmentSelector, isPlural);
370
+ return getFragmentState(environment, fragmentSelector);
311
371
  }),
312
- rawState = _useState[0],
313
- setState = _useState[1]; // On second look this separate rawState may not be needed at all, it can just be
314
- // put into getFragmentState. Exception: can we properly handle the case where the
315
- // fragmentRef goes from non-null to null?
316
-
372
+ _state = _useState[0],
373
+ setState = _useState[1];
317
374
 
318
- var stateFromRawState = function stateFromRawState(state) {
319
- if (fragmentRef == null) {
320
- return {
321
- kind: 'bailout'
322
- };
323
- } else if (state.kind === 'plural' && state.snapshots.length === 0) {
324
- return {
325
- kind: 'bailout'
326
- };
327
- } else {
328
- return state;
329
- }
330
- };
331
-
332
- var state = stateFromRawState(rawState); // This copy of the state we only update when something requires us to
375
+ var state = _state; // This copy of the state we only update when something requires us to
333
376
  // unsubscribe and re-subscribe, namely a changed environment or
334
377
  // fragment selector.
335
378
 
336
379
  var _useState2 = useState(state),
337
- rawSubscribedState = _useState2[0],
380
+ _subscribedState = _useState2[0],
338
381
  setSubscribedState = _useState2[1]; // FIXME since this is used as an effect dependency, it needs to be memoized.
339
382
 
340
383
 
341
- var subscribedState = stateFromRawState(rawSubscribedState);
384
+ var subscribedState = _subscribedState;
342
385
 
343
386
  var _useState3 = useState(fragmentSelector),
344
387
  previousFragmentSelector = _useState3[0],
@@ -352,7 +395,7 @@ function useFragmentInternal_REACT_CACHE(fragmentNode, fragmentRef, hookDisplayN
352
395
  // Enqueue setState to record the new selector and state
353
396
  setPreviousFragmentSelector(fragmentSelector);
354
397
  setPreviousEnvironment(environment);
355
- var newState = stateFromRawState(getFragmentState(environment, fragmentSelector, isPlural));
398
+ var newState = getFragmentState(environment, fragmentSelector);
356
399
  setState(newState);
357
400
  setSubscribedState(newState); // This causes us to form a new subscription
358
401
  // But render with the latest state w/o waiting for the setState. Otherwise
@@ -361,88 +404,115 @@ function useFragmentInternal_REACT_CACHE(fragmentNode, fragmentRef, hookDisplayN
361
404
 
362
405
  state = newState;
363
406
  subscribedState = newState;
364
- } // Handle the queries for any missing client edges; this may suspend.
365
- // FIXME handle client edges in parallel.
407
+ } // The purpose of this is to detect whether we have ever committed, because we
408
+ // don't suspend on store updates, only when the component either is first trying
409
+ // to mount or when the our selector changes. The selector change in particular is
410
+ // how we suspend for pagination and refetech. Also, fragment selector can be null
411
+ // or undefined, so we use false as a special value to distinguish from all fragment
412
+ // selectors; false means that the component hasn't mounted yet.
413
+
366
414
 
415
+ var committedFragmentSelectorRef = useRef(false);
416
+ useEffect(function () {
417
+ committedFragmentSelectorRef.current = fragmentSelector;
418
+ }, [fragmentSelector]); // Handle the queries for any missing client edges; this may suspend.
419
+ // FIXME handle client edges in parallel.
367
420
 
368
421
  if (((_fragmentNode$metadat2 = fragmentNode.metadata) === null || _fragmentNode$metadat2 === void 0 ? void 0 : _fragmentNode$metadat2.hasClientEdges) === true) {
369
422
  // The fragment is validated to be static (in useFragment) and hasClientEdges is
370
423
  // a static (constant) property of the fragment. In practice, this effect will
371
424
  // always or never run for a given invocation of this hook.
372
425
  // eslint-disable-next-line react-hooks/rules-of-hooks
373
- var effects = useMemo(function () {
426
+ var clientEdgeQueries = useMemo(function () {
374
427
  var missingClientEdges = getMissingClientEdges(state); // eslint-disable-next-line no-shadow
375
428
 
376
- var effects;
429
+ var clientEdgeQueries;
377
430
 
378
- if (missingClientEdges === null || missingClientEdges === void 0 ? void 0 : missingClientEdges.length) {
379
- effects = [];
431
+ if (missingClientEdges !== null && missingClientEdges !== void 0 && missingClientEdges.length) {
432
+ clientEdgeQueries = [];
380
433
 
381
- var _iterator5 = (0, _createForOfIteratorHelper2["default"])(missingClientEdges),
382
- _step5;
434
+ var _iterator7 = (0, _createForOfIteratorHelper2["default"])(missingClientEdges),
435
+ _step7;
383
436
 
384
437
  try {
385
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
386
- var edge = _step5.value;
387
- effects.push(handleMissingClientEdge(environment, fragmentNode, fragmentRef, edge, queryOptions));
438
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
439
+ var edge = _step7.value;
440
+ clientEdgeQueries.push(handleMissingClientEdge(environment, fragmentNode, fragmentRef, edge, queryOptions));
388
441
  }
389
442
  } catch (err) {
390
- _iterator5.e(err);
443
+ _iterator7.e(err);
391
444
  } finally {
392
- _iterator5.f();
445
+ _iterator7.f();
393
446
  }
394
447
  }
395
448
 
396
- return effects;
449
+ return clientEdgeQueries;
397
450
  }, [state, environment, fragmentNode, fragmentRef, queryOptions]); // See above note
398
451
  // eslint-disable-next-line react-hooks/rules-of-hooks
399
452
 
400
453
  useEffect(function () {
401
- if (effects === null || effects === void 0 ? void 0 : effects.length) {
402
- var cleanups = [];
454
+ var QueryResource = getQueryResourceForEnvironment(environment);
455
+
456
+ if (clientEdgeQueries !== null && clientEdgeQueries !== void 0 && clientEdgeQueries.length) {
457
+ var disposables = [];
403
458
 
404
- var _iterator6 = (0, _createForOfIteratorHelper2["default"])(effects),
405
- _step6;
459
+ var _iterator8 = (0, _createForOfIteratorHelper2["default"])(clientEdgeQueries),
460
+ _step8;
406
461
 
407
462
  try {
408
- for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
409
- var effect = _step6.value;
410
- cleanups.push(effect());
463
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
464
+ var query = _step8.value;
465
+ disposables.push(QueryResource.retain(query));
411
466
  }
412
467
  } catch (err) {
413
- _iterator6.e(err);
468
+ _iterator8.e(err);
414
469
  } finally {
415
- _iterator6.f();
470
+ _iterator8.f();
416
471
  }
417
472
 
418
473
  return function () {
419
- var _iterator7 = (0, _createForOfIteratorHelper2["default"])(cleanups),
420
- _step7;
474
+ var _iterator9 = (0, _createForOfIteratorHelper2["default"])(disposables),
475
+ _step9;
421
476
 
422
477
  try {
423
- for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
424
- var cleanup = _step7.value;
425
- cleanup();
478
+ for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
479
+ var disposable = _step9.value;
480
+ disposable.dispose();
426
481
  }
427
482
  } catch (err) {
428
- _iterator7.e(err);
483
+ _iterator9.e(err);
429
484
  } finally {
430
- _iterator7.f();
485
+ _iterator9.f();
431
486
  }
432
487
  };
433
488
  }
434
- }, [effects]);
489
+ }, [environment, clientEdgeQueries]);
435
490
  }
436
491
 
437
492
  if (isMissingData(state)) {
438
- // Suspend if an active operation bears on this fragment, either the
439
- // fragment's owner or some other mutation etc. that could affect it:
440
- !(fragmentSelector != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'refinement, see invariants above') : invariant(false) : void 0;
441
- var fragmentOwner = fragmentSelector.kind === 'PluralReaderSelector' ? fragmentSelector.selectors[0].owner : fragmentSelector.owner;
442
- var pendingOperationsResult = getPendingOperationsForFragment(environment, fragmentNode, fragmentOwner);
443
-
444
- if (pendingOperationsResult) {
445
- throw pendingOperationsResult.promise;
493
+ // Suspend if a Live Resolver within this fragment is in a suspended state:
494
+ var suspendingLiveResolvers = getSuspendingLiveResolver(state);
495
+
496
+ if (suspendingLiveResolvers != null && suspendingLiveResolvers.length > 0) {
497
+ throw Promise.all(suspendingLiveResolvers.map(function (_ref) {
498
+ var liveStateID = _ref.liveStateID;
499
+ // $FlowFixMe[prop-missing] This is expected to be a LiveResolverStore
500
+ return environment.getStore().getLiveResolverPromise(liveStateID);
501
+ }));
502
+ } // Suspend if an active operation bears on this fragment, either the
503
+ // fragment's owner or some other mutation etc. that could affect it.
504
+ // We only suspend when the component is first trying to mount or changing
505
+ // selectors, not if data becomes missing later:
506
+
507
+
508
+ if (!committedFragmentSelectorRef.current || !areEqualSelectors(committedFragmentSelectorRef.current, fragmentSelector)) {
509
+ !(fragmentSelector != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'refinement, see invariants above') : invariant(false) : void 0;
510
+ var fragmentOwner = fragmentSelector.kind === 'PluralReaderSelector' ? fragmentSelector.selectors[0].owner : fragmentSelector.owner;
511
+ var pendingOperationsResult = getPendingOperationsForFragment(environment, fragmentNode, fragmentOwner);
512
+
513
+ if (pendingOperationsResult) {
514
+ throw pendingOperationsResult.promise;
515
+ }
446
516
  } // Report required fields only if we're not suspending, since that means
447
517
  // they're missing even though we are out of options for possibly fetching them:
448
518
 
@@ -472,23 +542,7 @@ function useFragmentInternal_REACT_CACHE(fragmentNode, fragmentRef, hookDisplayN
472
542
  currentState = updatedState;
473
543
  }
474
544
 
475
- return subscribeToSnapshot(environment, currentState, function (updater) {
476
- setState(function (latestState) {
477
- var _latestState$snapshot, _currentState$snapsho;
478
-
479
- if (((_latestState$snapshot = latestState.snapshot) === null || _latestState$snapshot === void 0 ? void 0 : _latestState$snapshot.selector) !== ((_currentState$snapsho = currentState.snapshot) === null || _currentState$snapsho === void 0 ? void 0 : _currentState$snapsho.selector)) {
480
- // Ignore updates to the subscription if it's for a previous fragment selector
481
- // than the latest one to be rendered. This can happen if the store is updated
482
- // after we re-render with a new fragmentRef prop but before the effect fires
483
- // in which we unsubscribe to the old one and subscribe to the new one.
484
- // (NB: it's safe to compare the selectors by reference because the selector
485
- // is recycled into new snapshots.)
486
- return latestState;
487
- } else {
488
- return updater(latestState);
489
- }
490
- });
491
- });
545
+ return subscribeToSnapshot(environment, currentState, setState);
492
546
  }, [environment, subscribedState]);
493
547
  var data;
494
548
 
@@ -498,17 +552,21 @@ function useFragmentInternal_REACT_CACHE(fragmentNode, fragmentRef, hookDisplayN
498
552
  //
499
553
  // Note that isPlural is a constant property of the fragment and does not change
500
554
  // for a particular useFragment invocation site
555
+ var fragmentRefIsNullish = fragmentRef == null; // for less sensitive memoization
501
556
  // eslint-disable-next-line react-hooks/rules-of-hooks
557
+
502
558
  data = useMemo(function () {
503
559
  if (state.kind === 'bailout') {
504
- return [];
560
+ // Bailout state can happen if the fragmentRef is a plural array that is empty or has no
561
+ // non-null entries. In that case, the compatible behavior is to return [] instead of null.
562
+ return fragmentRefIsNullish ? null : [];
505
563
  } else {
506
564
  !(state.kind === 'plural') ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected state to be plural because fragment is plural') : invariant(false) : void 0;
507
565
  return state.snapshots.map(function (s) {
508
566
  return s.data;
509
567
  });
510
568
  }
511
- }, [state]);
569
+ }, [state, fragmentRefIsNullish]);
512
570
  } else if (state.kind === 'bailout') {
513
571
  // This case doesn't allocate a new object so it doesn't have to be memoized
514
572
  data = null;
@@ -8,7 +8,6 @@
8
8
  *
9
9
  * @format
10
10
  */
11
- // flowlint ambiguous-object-type:error
12
11
  'use strict';
13
12
 
14
13
  var _require = require('../loadQuery'),
@@ -8,7 +8,6 @@
8
8
  * @emails oncall+relay
9
9
  * @format
10
10
  */
11
- // flowlint ambiguous-object-type:error
12
11
  'use strict';
13
12
 
14
13
  var _require = require('../loadQuery'),
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @emails oncall+relay
8
+ *
9
+ * @format
10
+ */
11
+ 'use strict';
12
+
13
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
14
+
15
+ var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
16
+
17
+ var useLoadMoreFunction = require('../useLoadMoreFunction');
18
+
19
+ var useStaticFragmentNodeWarning = require('../useStaticFragmentNodeWarning');
20
+
21
+ var useRefetchableFragmentInternal = require('./useRefetchableFragmentInternal_REACT_CACHE');
22
+
23
+ var _require = require('react'),
24
+ useCallback = _require.useCallback,
25
+ useDebugValue = _require.useDebugValue,
26
+ useState = _require.useState;
27
+
28
+ var _require2 = require('relay-runtime'),
29
+ getFragment = _require2.getFragment,
30
+ getFragmentIdentifier = _require2.getFragmentIdentifier,
31
+ getPaginationMetadata = _require2.getPaginationMetadata;
32
+
33
+ function usePaginationFragment(fragmentInput, parentFragmentRef) {
34
+ var fragmentNode = getFragment(fragmentInput);
35
+ useStaticFragmentNodeWarning(fragmentNode, 'first argument of usePaginationFragment()');
36
+ var componentDisplayName = 'usePaginationFragment()';
37
+
38
+ var _getPaginationMetadat = getPaginationMetadata(fragmentNode, componentDisplayName),
39
+ connectionPathInFragmentData = _getPaginationMetadat.connectionPathInFragmentData,
40
+ paginationRequest = _getPaginationMetadat.paginationRequest,
41
+ paginationMetadata = _getPaginationMetadat.paginationMetadata,
42
+ identifierField = _getPaginationMetadat.identifierField;
43
+
44
+ var _useRefetchableFragme = useRefetchableFragmentInternal(fragmentNode, parentFragmentRef, componentDisplayName),
45
+ fragmentData = _useRefetchableFragme.fragmentData,
46
+ fragmentRef = _useRefetchableFragme.fragmentRef,
47
+ refetch = _useRefetchableFragme.refetch;
48
+
49
+ var fragmentIdentifier = getFragmentIdentifier(fragmentNode, fragmentRef); // Backward pagination
50
+
51
+ var _useLoadMore = useLoadMore({
52
+ componentDisplayName: componentDisplayName,
53
+ connectionPathInFragmentData: connectionPathInFragmentData,
54
+ direction: 'backward',
55
+ fragmentData: fragmentData,
56
+ fragmentIdentifier: fragmentIdentifier,
57
+ fragmentNode: fragmentNode,
58
+ fragmentRef: fragmentRef,
59
+ identifierField: identifierField,
60
+ paginationMetadata: paginationMetadata,
61
+ paginationRequest: paginationRequest
62
+ }),
63
+ loadPrevious = _useLoadMore[0],
64
+ hasPrevious = _useLoadMore[1],
65
+ isLoadingPrevious = _useLoadMore[2],
66
+ disposeFetchPrevious = _useLoadMore[3]; // Forward pagination
67
+
68
+
69
+ var _useLoadMore2 = useLoadMore({
70
+ componentDisplayName: componentDisplayName,
71
+ connectionPathInFragmentData: connectionPathInFragmentData,
72
+ direction: 'forward',
73
+ fragmentData: fragmentData,
74
+ fragmentIdentifier: fragmentIdentifier,
75
+ fragmentNode: fragmentNode,
76
+ fragmentRef: fragmentRef,
77
+ identifierField: identifierField,
78
+ paginationMetadata: paginationMetadata,
79
+ paginationRequest: paginationRequest
80
+ }),
81
+ loadNext = _useLoadMore2[0],
82
+ hasNext = _useLoadMore2[1],
83
+ isLoadingNext = _useLoadMore2[2],
84
+ disposeFetchNext = _useLoadMore2[3];
85
+
86
+ var refetchPagination = useCallback(function (variables, options) {
87
+ disposeFetchNext();
88
+ disposeFetchPrevious();
89
+ return refetch(variables, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, options), {}, {
90
+ __environment: undefined
91
+ }));
92
+ }, [disposeFetchNext, disposeFetchPrevious, refetch]);
93
+
94
+ if (process.env.NODE_ENV !== "production") {
95
+ // eslint-disable-next-line react-hooks/rules-of-hooks
96
+ useDebugValue({
97
+ fragment: fragmentNode.name,
98
+ data: fragmentData,
99
+ hasNext: hasNext,
100
+ isLoadingNext: isLoadingNext,
101
+ hasPrevious: hasPrevious,
102
+ isLoadingPrevious: isLoadingPrevious
103
+ });
104
+ }
105
+
106
+ return {
107
+ data: fragmentData,
108
+ loadNext: loadNext,
109
+ loadPrevious: loadPrevious,
110
+ hasNext: hasNext,
111
+ hasPrevious: hasPrevious,
112
+ isLoadingNext: isLoadingNext,
113
+ isLoadingPrevious: isLoadingPrevious,
114
+ refetch: refetchPagination
115
+ };
116
+ }
117
+
118
+ function useLoadMore(args) {
119
+ var _useState = useState(false),
120
+ isLoadingMore = _useState[0],
121
+ setIsLoadingMore = _useState[1];
122
+
123
+ var observer = {
124
+ start: function start() {
125
+ return setIsLoadingMore(true);
126
+ },
127
+ complete: function complete() {
128
+ return setIsLoadingMore(false);
129
+ },
130
+ error: function error() {
131
+ return setIsLoadingMore(false);
132
+ }
133
+ };
134
+
135
+ var handleReset = function handleReset() {
136
+ return setIsLoadingMore(false);
137
+ };
138
+
139
+ var _useLoadMoreFunction = useLoadMoreFunction((0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, args), {}, {
140
+ observer: observer,
141
+ onReset: handleReset
142
+ })),
143
+ loadMore = _useLoadMoreFunction[0],
144
+ hasMore = _useLoadMoreFunction[1],
145
+ disposeFetch = _useLoadMoreFunction[2];
146
+
147
+ return [loadMore, hasMore, isLoadingMore, disposeFetch];
148
+ }
149
+
150
+ module.exports = usePaginationFragment;
@@ -8,7 +8,6 @@
8
8
  * @emails oncall+relay
9
9
  * @format
10
10
  */
11
- // flowlint ambiguous-object-type:error
12
11
  'use strict';
13
12
 
14
13
  var _require = require('../loadQuery'),