react-relay 14.0.0 → 14.1.0

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