react-relay 13.1.0 → 14.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. package/ReactRelayContext.js +1 -1
  2. package/ReactRelayFragmentContainer.js.flow +7 -4
  3. package/ReactRelayLocalQueryRenderer.js.flow +1 -1
  4. package/ReactRelayPaginationContainer.js.flow +13 -8
  5. package/ReactRelayQueryFetcher.js.flow +1 -0
  6. package/ReactRelayQueryRenderer.js.flow +7 -6
  7. package/ReactRelayRefetchContainer.js.flow +10 -3
  8. package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer.graphql.js.flow +2 -2
  9. package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer2.graphql.js.flow +2 -2
  10. package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtestQuery.graphql.js.flow +3 -3
  11. package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtest_viewer.graphql.js.flow +3 -3
  12. package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtestQuery.graphql.js.flow +3 -3
  13. package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtest_viewer.graphql.js.flow +3 -3
  14. package/__flowtests__/__generated__/RelayModernFlowtest_badref.graphql.js.flow +2 -2
  15. package/__flowtests__/__generated__/RelayModernFlowtest_notref.graphql.js.flow +2 -2
  16. package/__flowtests__/__generated__/RelayModernFlowtest_user.graphql.js.flow +2 -2
  17. package/__flowtests__/__generated__/RelayModernFlowtest_users.graphql.js.flow +2 -2
  18. package/buildReactRelayContainer.js.flow +2 -2
  19. package/hooks.js +1 -1
  20. package/index.js +1 -1
  21. package/jest-react/internalAct.js.flow +25 -9
  22. package/legacy.js +1 -1
  23. package/lib/ReactRelayQueryFetcher.js +1 -0
  24. package/lib/ReactRelayQueryRenderer.js +1 -2
  25. package/lib/jest-react/internalAct.js +24 -4
  26. package/lib/readContext.js +2 -1
  27. package/lib/relay-hooks/FragmentResource.js +62 -23
  28. package/lib/relay-hooks/HooksImplementation.js +29 -0
  29. package/lib/relay-hooks/MatchContainer.js +1 -0
  30. package/lib/relay-hooks/QueryResource.js +4 -166
  31. package/lib/relay-hooks/preloadQuery_DEPRECATED.js +7 -11
  32. package/lib/relay-hooks/react-cache/RelayReactCache.js +37 -0
  33. package/lib/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js +344 -0
  34. package/lib/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js +540 -0
  35. package/lib/relay-hooks/react-cache/useFragment_REACT_CACHE.js +51 -0
  36. package/lib/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js +56 -0
  37. package/lib/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js +125 -0
  38. package/lib/relay-hooks/useFragment.js +15 -1
  39. package/lib/relay-hooks/useLazyLoadQuery.js +18 -2
  40. package/lib/relay-hooks/useMutation.js +4 -5
  41. package/lib/relay-hooks/usePreloadedQuery.js +18 -2
  42. package/package.json +3 -3
  43. package/react-relay-hooks.js +2 -2
  44. package/react-relay-hooks.min.js +2 -2
  45. package/react-relay-legacy.js +2 -2
  46. package/react-relay-legacy.min.js +2 -2
  47. package/react-relay.js +2 -2
  48. package/react-relay.min.js +2 -2
  49. package/readContext.js.flow +1 -0
  50. package/relay-hooks/FragmentResource.js.flow +72 -27
  51. package/relay-hooks/HooksImplementation.js.flow +45 -0
  52. package/relay-hooks/MatchContainer.js.flow +8 -1
  53. package/relay-hooks/QueryResource.js.flow +8 -203
  54. package/relay-hooks/__flowtests__/__generated__/useFragmentFlowtest_user.graphql.js.flow +2 -2
  55. package/relay-hooks/__flowtests__/__generated__/useFragmentFlowtest_users.graphql.js.flow +2 -2
  56. package/relay-hooks/loadQuery.js.flow +2 -1
  57. package/relay-hooks/preloadQuery_DEPRECATED.js.flow +7 -14
  58. package/relay-hooks/react-cache/RelayReactCache.js.flow +42 -0
  59. package/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js.flow +424 -0
  60. package/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js.flow +559 -0
  61. package/relay-hooks/react-cache/useFragment_REACT_CACHE.js.flow +74 -0
  62. package/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js.flow +72 -0
  63. package/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js.flow +153 -0
  64. package/relay-hooks/useFragment.js.flow +17 -10
  65. package/relay-hooks/useLazyLoadQuery.js.flow +38 -3
  66. package/relay-hooks/useMutation.js.flow +3 -3
  67. package/relay-hooks/usePreloadedQuery.js.flow +30 -2
  68. package/relay-hooks/useRefetchableFragmentNode.js.flow +26 -11
  69. package/relay-hooks/useSubscription.js.flow +14 -8
@@ -0,0 +1,540 @@
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
+ *
8
+ * @emails oncall+relay
9
+ * @format
10
+ */
11
+ // flowlint ambiguous-object-type:error
12
+ 'use strict';
13
+
14
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
15
+
16
+ var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
17
+
18
+ var _createForOfIteratorHelper2 = _interopRequireDefault(require("@babel/runtime/helpers/createForOfIteratorHelper"));
19
+
20
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
21
+
22
+ var useRelayEnvironment = require('../useRelayEnvironment');
23
+
24
+ var getQueryResultOrFetchQuery = require('./getQueryResultOrFetchQuery_REACT_CACHE');
25
+
26
+ var invariant = require('invariant');
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;
43
+
44
+ var warning = require("fbjs/lib/warning");
45
+
46
+ function isMissingData(state) {
47
+ if (state.kind === 'bailout') {
48
+ return false;
49
+ } else if (state.kind === 'singular') {
50
+ return state.snapshot.isMissingData;
51
+ } else {
52
+ return state.snapshots.some(function (s) {
53
+ return s.isMissingData;
54
+ });
55
+ }
56
+ }
57
+
58
+ function getMissingClientEdges(state) {
59
+ if (state.kind === 'bailout') {
60
+ return null;
61
+ } else if (state.kind === 'singular') {
62
+ var _state$snapshot$missi;
63
+
64
+ return (_state$snapshot$missi = state.snapshot.missingClientEdges) !== null && _state$snapshot$missi !== void 0 ? _state$snapshot$missi : null;
65
+ } else {
66
+ var edges = null;
67
+
68
+ var _iterator = (0, _createForOfIteratorHelper2["default"])(state.snapshots),
69
+ _step;
70
+
71
+ try {
72
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
73
+ var snapshot = _step.value;
74
+
75
+ if (snapshot.missingClientEdges) {
76
+ var _edges;
77
+
78
+ edges = (_edges = edges) !== null && _edges !== void 0 ? _edges : [];
79
+
80
+ var _iterator2 = (0, _createForOfIteratorHelper2["default"])(snapshot.missingClientEdges),
81
+ _step2;
82
+
83
+ try {
84
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
85
+ var edge = _step2.value;
86
+ edges.push(edge);
87
+ }
88
+ } catch (err) {
89
+ _iterator2.e(err);
90
+ } finally {
91
+ _iterator2.f();
92
+ }
93
+ }
94
+ }
95
+ } catch (err) {
96
+ _iterator.e(err);
97
+ } finally {
98
+ _iterator.f();
99
+ }
100
+
101
+ return edges;
102
+ }
103
+ }
104
+
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') {
109
+ var _iterator3 = (0, _createForOfIteratorHelper2["default"])(state.snapshots),
110
+ _step3;
111
+
112
+ try {
113
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
114
+ var snapshot = _step3.value;
115
+ handlePotentialSnapshotErrors(environment, snapshot.missingRequiredFields, snapshot.relayResolverErrors);
116
+ }
117
+ } catch (err) {
118
+ _iterator3.e(err);
119
+ } finally {
120
+ _iterator3.f();
121
+ }
122
+ }
123
+ }
124
+ /**
125
+ * Check for updates to the store that occurred concurrently with rendering the given `state` value,
126
+ * returning a new (updated) state if there were updates or null if there were no changes.
127
+ */
128
+
129
+
130
+ function handleMissedUpdates(environment, state) {
131
+ if (state.kind === 'bailout') {
132
+ return null;
133
+ } // FIXME this is invalid if we've just switched environments.
134
+
135
+
136
+ var currentEpoch = environment.getStore().getEpoch();
137
+
138
+ if (currentEpoch === state.epoch) {
139
+ return null;
140
+ } // The store has updated since we rendered (without us being subscribed yet),
141
+ // so check for any updates to the data we're rendering:
142
+
143
+
144
+ if (state.kind === 'singular') {
145
+ var currentSnapshot = environment.lookup(state.snapshot.selector);
146
+ var updatedData = recycleNodesInto(state.snapshot.data, currentSnapshot.data);
147
+ var updatedCurrentSnapshot = {
148
+ data: updatedData,
149
+ isMissingData: currentSnapshot.isMissingData,
150
+ missingClientEdges: currentSnapshot.missingClientEdges,
151
+ missingLiveResolverFields: currentSnapshot.missingLiveResolverFields,
152
+ seenRecords: currentSnapshot.seenRecords,
153
+ selector: currentSnapshot.selector,
154
+ missingRequiredFields: currentSnapshot.missingRequiredFields,
155
+ relayResolverErrors: currentSnapshot.relayResolverErrors
156
+ };
157
+ return [updatedData !== state.snapshot.data, {
158
+ kind: 'singular',
159
+ snapshot: updatedCurrentSnapshot,
160
+ epoch: currentEpoch
161
+ }];
162
+ } else {
163
+ var didMissUpdates = false;
164
+ var currentSnapshots = [];
165
+
166
+ for (var index = 0; index < state.snapshots.length; index++) {
167
+ var snapshot = state.snapshots[index];
168
+
169
+ var _currentSnapshot = environment.lookup(snapshot.selector);
170
+
171
+ var _updatedData = recycleNodesInto(snapshot.data, _currentSnapshot.data);
172
+
173
+ var _updatedCurrentSnapshot = {
174
+ data: _updatedData,
175
+ isMissingData: _currentSnapshot.isMissingData,
176
+ missingClientEdges: _currentSnapshot.missingClientEdges,
177
+ missingLiveResolverFields: _currentSnapshot.missingLiveResolverFields,
178
+ seenRecords: _currentSnapshot.seenRecords,
179
+ selector: _currentSnapshot.selector,
180
+ missingRequiredFields: _currentSnapshot.missingRequiredFields,
181
+ relayResolverErrors: _currentSnapshot.relayResolverErrors
182
+ };
183
+
184
+ if (_updatedData !== snapshot.data) {
185
+ didMissUpdates = true;
186
+ }
187
+
188
+ currentSnapshots.push(_updatedCurrentSnapshot);
189
+ }
190
+
191
+ !(currentSnapshots.length === state.snapshots.length) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected same number of snapshots') : invariant(false) : void 0;
192
+ return [didMissUpdates, {
193
+ kind: 'plural',
194
+ snapshots: currentSnapshots,
195
+ epoch: currentEpoch
196
+ }];
197
+ }
198
+ }
199
+
200
+ function handleMissingClientEdge(environment, parentFragmentNode, parentFragmentRef, missingClientEdgeRequestInfo, queryOptions) {
201
+ var originalVariables = getVariablesFromFragment(parentFragmentNode, parentFragmentRef);
202
+ var variables = (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, originalVariables), {}, {
203
+ id: missingClientEdgeRequestInfo.clientEdgeDestinationID // TODO should be a reserved name
204
+
205
+ });
206
+ 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
+ // doing here is started the query if needed and retaining and releasing it
208
+ // according to the component mount/suspense cycle; getQueryResultOrFetchQuery
209
+ // already handles this by itself.
210
+
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;
218
+ }
219
+
220
+ function subscribeToSnapshot(environment, state, setState) {
221
+ if (state.kind === 'bailout') {
222
+ return function () {};
223
+ } else if (state.kind === 'singular') {
224
+ var disposable = environment.subscribe(state.snapshot, function (latestSnapshot) {
225
+ setState(function (_) {
226
+ return {
227
+ kind: 'singular',
228
+ snapshot: latestSnapshot,
229
+ epoch: environment.getStore().getEpoch()
230
+ };
231
+ });
232
+ });
233
+ return function () {
234
+ disposable.dispose();
235
+ };
236
+ } else {
237
+ var disposables = state.snapshots.map(function (snapshot, index) {
238
+ 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);
242
+ updated[index] = latestSnapshot;
243
+ return {
244
+ kind: 'plural',
245
+ snapshots: updated,
246
+ epoch: environment.getStore().getEpoch()
247
+ };
248
+ });
249
+ });
250
+ });
251
+ return function () {
252
+ var _iterator4 = (0, _createForOfIteratorHelper2["default"])(disposables),
253
+ _step4;
254
+
255
+ try {
256
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
257
+ var d = _step4.value;
258
+ d.dispose();
259
+ }
260
+ } catch (err) {
261
+ _iterator4.e(err);
262
+ } finally {
263
+ _iterator4.f();
264
+ }
265
+ };
266
+ }
267
+ }
268
+
269
+ function getFragmentState(environment, fragmentSelector, isPlural) {
270
+ if (fragmentSelector == null) {
271
+ return {
272
+ kind: 'bailout'
273
+ };
274
+ } else if (fragmentSelector.kind === 'PluralReaderSelector') {
275
+ return {
276
+ kind: 'plural',
277
+ snapshots: fragmentSelector.selectors.map(function (s) {
278
+ return environment.lookup(s);
279
+ }),
280
+ epoch: environment.getStore().getEpoch()
281
+ };
282
+ } else {
283
+ return {
284
+ kind: 'singular',
285
+ snapshot: environment.lookup(fragmentSelector),
286
+ epoch: environment.getStore().getEpoch()
287
+ };
288
+ }
289
+ } // fragmentNode cannot change during the lifetime of the component, though fragmentRef may change.
290
+
291
+
292
+ function useFragmentInternal_REACT_CACHE(fragmentNode, fragmentRef, hookDisplayName, queryOptions, fragmentKey) {
293
+ var _fragmentNode$metadat, _fragmentNode$metadat2;
294
+
295
+ var fragmentSelector = useMemo(function () {
296
+ return getSelector(fragmentNode, fragmentRef);
297
+ }, [fragmentNode, fragmentRef]);
298
+ var isPlural = (fragmentNode === null || fragmentNode === void 0 ? void 0 : (_fragmentNode$metadat = fragmentNode.metadata) === null || _fragmentNode$metadat === void 0 ? void 0 : _fragmentNode$metadat.plural) === true;
299
+
300
+ if (isPlural) {
301
+ !(fragmentRef == null || Array.isArray(fragmentRef)) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected fragment pointer%s for fragment `%s` to be ' + 'an array, instead got `%s`. Remove `@relay(plural: true)` ' + 'from fragment `%s` to allow the prop to be an object.', fragmentKey != null ? " for key `".concat(fragmentKey, "`") : '', fragmentNode.name, typeof fragmentRef, fragmentNode.name) : invariant(false) : void 0;
302
+ } else {
303
+ !!Array.isArray(fragmentRef) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected fragment pointer%s for fragment `%s` not to be ' + 'an array, instead got `%s`. Add `@relay(plural: true)` ' + 'to fragment `%s` to allow the prop to be an array.', fragmentKey != null ? " for key `".concat(fragmentKey, "`") : '', fragmentNode.name, typeof fragmentRef, fragmentNode.name) : invariant(false) : void 0;
304
+ }
305
+
306
+ !(fragmentRef == null || isPlural && Array.isArray(fragmentRef) && fragmentRef.length === 0 || fragmentSelector != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected to receive an object where `...%s` was spread, ' + 'but the fragment reference was not found`. This is most ' + 'likely the result of:\n' + "- Forgetting to spread `%s` in `%s`'s parent's fragment.\n" + '- Conditionally fetching `%s` but unconditionally passing %s prop ' + 'to `%s`. If the parent fragment only fetches the fragment conditionally ' + '- with e.g. `@include`, `@skip`, or inside a `... on SomeType { }` ' + 'spread - then the fragment reference will not exist. ' + 'In this case, pass `null` if the conditions for evaluating the ' + 'fragment are not met (e.g. if the `@include(if)` value is false.)', fragmentNode.name, fragmentNode.name, hookDisplayName, fragmentNode.name, fragmentKey == null ? 'a fragment reference' : "the `".concat(fragmentKey, "`"), hookDisplayName) : invariant(false) : void 0;
307
+ var environment = useRelayEnvironment();
308
+
309
+ var _useState = useState(function () {
310
+ return getFragmentState(environment, fragmentSelector, isPlural);
311
+ }),
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
+
317
+
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
333
+ // unsubscribe and re-subscribe, namely a changed environment or
334
+ // fragment selector.
335
+
336
+ var _useState2 = useState(state),
337
+ rawSubscribedState = _useState2[0],
338
+ setSubscribedState = _useState2[1]; // FIXME since this is used as an effect dependency, it needs to be memoized.
339
+
340
+
341
+ var subscribedState = stateFromRawState(rawSubscribedState);
342
+
343
+ var _useState3 = useState(fragmentSelector),
344
+ previousFragmentSelector = _useState3[0],
345
+ setPreviousFragmentSelector = _useState3[1];
346
+
347
+ var _useState4 = useState(environment),
348
+ previousEnvironment = _useState4[0],
349
+ setPreviousEnvironment = _useState4[1];
350
+
351
+ if (!areEqualSelectors(fragmentSelector, previousFragmentSelector) || environment !== previousEnvironment) {
352
+ // Enqueue setState to record the new selector and state
353
+ setPreviousFragmentSelector(fragmentSelector);
354
+ setPreviousEnvironment(environment);
355
+ var newState = stateFromRawState(getFragmentState(environment, fragmentSelector, isPlural));
356
+ setState(newState);
357
+ setSubscribedState(newState); // This causes us to form a new subscription
358
+ // But render with the latest state w/o waiting for the setState. Otherwise
359
+ // the component would render the wrong information temporarily (including
360
+ // possibly incorrectly triggering some warnings below).
361
+
362
+ state = newState;
363
+ subscribedState = newState;
364
+ } // Handle the queries for any missing client edges; this may suspend.
365
+ // FIXME handle client edges in parallel.
366
+
367
+
368
+ if (((_fragmentNode$metadat2 = fragmentNode.metadata) === null || _fragmentNode$metadat2 === void 0 ? void 0 : _fragmentNode$metadat2.hasClientEdges) === true) {
369
+ // The fragment is validated to be static (in useFragment) and hasClientEdges is
370
+ // a static (constant) property of the fragment. In practice, this effect will
371
+ // always or never run for a given invocation of this hook.
372
+ // eslint-disable-next-line react-hooks/rules-of-hooks
373
+ var effects = useMemo(function () {
374
+ var missingClientEdges = getMissingClientEdges(state); // eslint-disable-next-line no-shadow
375
+
376
+ var effects;
377
+
378
+ if (missingClientEdges === null || missingClientEdges === void 0 ? void 0 : missingClientEdges.length) {
379
+ effects = [];
380
+
381
+ var _iterator5 = (0, _createForOfIteratorHelper2["default"])(missingClientEdges),
382
+ _step5;
383
+
384
+ try {
385
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
386
+ var edge = _step5.value;
387
+ effects.push(handleMissingClientEdge(environment, fragmentNode, fragmentRef, edge, queryOptions));
388
+ }
389
+ } catch (err) {
390
+ _iterator5.e(err);
391
+ } finally {
392
+ _iterator5.f();
393
+ }
394
+ }
395
+
396
+ return effects;
397
+ }, [state, environment, fragmentNode, fragmentRef, queryOptions]); // See above note
398
+ // eslint-disable-next-line react-hooks/rules-of-hooks
399
+
400
+ useEffect(function () {
401
+ if (effects === null || effects === void 0 ? void 0 : effects.length) {
402
+ var cleanups = [];
403
+
404
+ var _iterator6 = (0, _createForOfIteratorHelper2["default"])(effects),
405
+ _step6;
406
+
407
+ try {
408
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
409
+ var effect = _step6.value;
410
+ cleanups.push(effect());
411
+ }
412
+ } catch (err) {
413
+ _iterator6.e(err);
414
+ } finally {
415
+ _iterator6.f();
416
+ }
417
+
418
+ return function () {
419
+ var _iterator7 = (0, _createForOfIteratorHelper2["default"])(cleanups),
420
+ _step7;
421
+
422
+ try {
423
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
424
+ var cleanup = _step7.value;
425
+ cleanup();
426
+ }
427
+ } catch (err) {
428
+ _iterator7.e(err);
429
+ } finally {
430
+ _iterator7.f();
431
+ }
432
+ };
433
+ }
434
+ }, [effects]);
435
+ }
436
+
437
+ 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;
446
+ } // Report required fields only if we're not suspending, since that means
447
+ // they're missing even though we are out of options for possibly fetching them:
448
+
449
+
450
+ handlePotentialSnapshotErrorsForState(environment, state);
451
+ }
452
+
453
+ useEffect(function () {
454
+ // Check for updates since the state was rendered
455
+ var currentState = subscribedState;
456
+ var updates = handleMissedUpdates(environment, subscribedState);
457
+
458
+ if (updates !== null) {
459
+ var didMissUpdates = updates[0],
460
+ updatedState = updates[1]; // TODO: didMissUpdates only checks for changes to snapshot data, but it's possible
461
+ // that other snapshot properties may have changed that should also trigger a re-render,
462
+ // such as changed missing resolver fields, missing client edges, etc.
463
+ // A potential alternative is for handleMissedUpdates() to recycle the entire state
464
+ // value, and return the new (recycled) state only if there was some change. In that
465
+ // case the code would always setState if something in the snapshot changed, in addition
466
+ // to using the latest snapshot to subscribe.
467
+
468
+ if (didMissUpdates) {
469
+ setState(updatedState);
470
+ }
471
+
472
+ currentState = updatedState;
473
+ }
474
+
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
+ });
492
+ }, [environment, subscribedState]);
493
+ var data;
494
+
495
+ if (isPlural) {
496
+ // Plural fragments require allocating an array of the snasphot data values,
497
+ // which has to be memoized to avoid triggering downstream re-renders.
498
+ //
499
+ // Note that isPlural is a constant property of the fragment and does not change
500
+ // for a particular useFragment invocation site
501
+ // eslint-disable-next-line react-hooks/rules-of-hooks
502
+ data = useMemo(function () {
503
+ if (state.kind === 'bailout') {
504
+ return [];
505
+ } else {
506
+ !(state.kind === 'plural') ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected state to be plural because fragment is plural') : invariant(false) : void 0;
507
+ return state.snapshots.map(function (s) {
508
+ return s.data;
509
+ });
510
+ }
511
+ }, [state]);
512
+ } else if (state.kind === 'bailout') {
513
+ // This case doesn't allocate a new object so it doesn't have to be memoized
514
+ data = null;
515
+ } else {
516
+ // This case doesn't allocate a new object so it doesn't have to be memoized
517
+ !(state.kind === 'singular') ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected state to be singular because fragment is singular') : invariant(false) : void 0;
518
+ data = state.snapshot.data;
519
+ }
520
+
521
+ if (process.env.NODE_ENV !== "production") {
522
+ if (fragmentRef != null && (data === undefined || Array.isArray(data) && data.length > 0 && data.every(function (d) {
523
+ return d === undefined;
524
+ }))) {
525
+ process.env.NODE_ENV !== "production" ? warning(false, 'Relay: Expected to have been able to read non-null data for ' + 'fragment `%s` declared in ' + '`%s`, since fragment reference was non-null. ' + "Make sure that that `%s`'s parent isn't " + 'holding on to and/or passing a fragment reference for data that ' + 'has been deleted.', fragmentNode.name, hookDisplayName, hookDisplayName) : void 0;
526
+ }
527
+ }
528
+
529
+ if (process.env.NODE_ENV !== "production") {
530
+ // eslint-disable-next-line react-hooks/rules-of-hooks
531
+ useDebugValue({
532
+ fragment: fragmentNode.name,
533
+ data: data
534
+ });
535
+ }
536
+
537
+ return data;
538
+ }
539
+
540
+ module.exports = useFragmentInternal_REACT_CACHE;
@@ -0,0 +1,51 @@
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
+ // flowlint ambiguous-object-type:error
12
+ 'use strict';
13
+
14
+ var _require = require('../loadQuery'),
15
+ useTrackLoadQueryInRender = _require.useTrackLoadQueryInRender;
16
+
17
+ var useStaticFragmentNodeWarning = require('../useStaticFragmentNodeWarning');
18
+
19
+ var useFragmentInternal = require('./useFragmentInternal_REACT_CACHE');
20
+
21
+ var _require2 = require('react'),
22
+ useDebugValue = _require2.useDebugValue;
23
+
24
+ var _require3 = require('relay-runtime'),
25
+ getFragment = _require3.getFragment;
26
+
27
+ function useFragment(fragment, key) {
28
+ // We need to use this hook in order to be able to track if
29
+ // loadQuery was called during render
30
+ useTrackLoadQueryInRender();
31
+ var fragmentNode = getFragment(fragment);
32
+
33
+ if (process.env.NODE_ENV !== "production") {
34
+ // eslint-disable-next-line react-hooks/rules-of-hooks
35
+ useStaticFragmentNodeWarning(fragmentNode, 'first argument of useFragment()');
36
+ }
37
+
38
+ var data = useFragmentInternal(fragmentNode, key, 'useFragment()');
39
+
40
+ if (process.env.NODE_ENV !== "production") {
41
+ // eslint-disable-next-line react-hooks/rules-of-hooks
42
+ useDebugValue({
43
+ fragment: fragmentNode.name,
44
+ data: data
45
+ });
46
+ }
47
+
48
+ return data;
49
+ }
50
+
51
+ module.exports = useFragment;
@@ -0,0 +1,56 @@
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
+ *
8
+ * @emails oncall+relay
9
+ * @format
10
+ */
11
+ // flowlint ambiguous-object-type:error
12
+ 'use strict';
13
+
14
+ var _require = require('../loadQuery'),
15
+ useTrackLoadQueryInRender = _require.useTrackLoadQueryInRender;
16
+
17
+ var useMemoOperationDescriptor = require('../useMemoOperationDescriptor');
18
+
19
+ var useRelayEnvironment = require('../useRelayEnvironment');
20
+
21
+ var getQueryResultOrFetchQuery = require('./getQueryResultOrFetchQuery_REACT_CACHE');
22
+
23
+ var useFragmentInternal = require('./useFragmentInternal_REACT_CACHE');
24
+
25
+ var _require2 = require('react'),
26
+ useEffect = _require2.useEffect;
27
+
28
+ function useLazyLoadQuery_REACT_CACHE(gqlQuery, variables, options) {
29
+ var _options$networkCache;
30
+
31
+ useTrackLoadQueryInRender();
32
+ var environment = useRelayEnvironment();
33
+ var queryOperationDescriptor = useMemoOperationDescriptor(gqlQuery, variables, (_options$networkCache = options === null || options === void 0 ? void 0 : options.networkCacheConfig) !== null && _options$networkCache !== void 0 ? _options$networkCache : {
34
+ force: true
35
+ }); // Get the query going if needed -- this may suspend.
36
+
37
+ var _getQueryResultOrFetc = getQueryResultOrFetchQuery(environment, queryOperationDescriptor, {
38
+ fetchPolicy: options === null || options === void 0 ? void 0 : options.fetchPolicy,
39
+ renderPolicy: options === null || options === void 0 ? void 0 : options.UNSTABLE_renderPolicy,
40
+ fetchKey: options === null || options === void 0 ? void 0 : options.fetchKey
41
+ }),
42
+ queryResult = _getQueryResultOrFetc[0],
43
+ effect = _getQueryResultOrFetc[1];
44
+
45
+ useEffect(effect); // Read the query's root fragment -- this may suspend.
46
+
47
+ var fragmentNode = queryResult.fragmentNode,
48
+ fragmentRef = queryResult.fragmentRef; // $FlowExpectedError[incompatible-return] Is this a fixable incompatible-return?
49
+
50
+ return useFragmentInternal(fragmentNode, fragmentRef, 'useLazyLoadQuery()', {
51
+ fetchPolicy: options === null || options === void 0 ? void 0 : options.fetchPolicy,
52
+ networkCacheConfig: options === null || options === void 0 ? void 0 : options.networkCacheConfig
53
+ });
54
+ }
55
+
56
+ module.exports = useLazyLoadQuery_REACT_CACHE;