react-relay 13.1.1 → 13.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. package/ReactRelayContext.js +1 -1
  2. package/ReactRelayLocalQueryRenderer.js.flow +1 -1
  3. package/ReactRelayQueryRenderer.js.flow +1 -4
  4. package/hooks.js +1 -1
  5. package/index.js +1 -1
  6. package/jest-react/internalAct.js.flow +25 -9
  7. package/legacy.js +1 -1
  8. package/lib/ReactRelayQueryRenderer.js +1 -1
  9. package/lib/jest-react/internalAct.js +24 -4
  10. package/lib/relay-hooks/FragmentResource.js +10 -13
  11. package/lib/relay-hooks/QueryResource.js +2 -165
  12. package/lib/relay-hooks/preloadQuery_DEPRECATED.js +7 -11
  13. package/lib/relay-hooks/react-cache/RelayReactCache.js +37 -0
  14. package/lib/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js +197 -0
  15. package/lib/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js +395 -0
  16. package/lib/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js +45 -0
  17. package/package.json +3 -3
  18. package/react-relay-hooks.js +2 -2
  19. package/react-relay-hooks.min.js +2 -2
  20. package/react-relay-legacy.js +2 -2
  21. package/react-relay-legacy.min.js +2 -2
  22. package/react-relay.js +2 -2
  23. package/react-relay.min.js +2 -2
  24. package/relay-hooks/FragmentResource.js.flow +17 -18
  25. package/relay-hooks/QueryResource.js.flow +4 -201
  26. package/relay-hooks/preloadQuery_DEPRECATED.js.flow +7 -14
  27. package/relay-hooks/react-cache/RelayReactCache.js.flow +42 -0
  28. package/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js.flow +243 -0
  29. package/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js.flow +416 -0
  30. package/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js.flow +66 -0
@@ -0,0 +1,197 @@
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 _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
17
+
18
+ var _require = require('./RelayReactCache'),
19
+ getCacheForType = _require.getCacheForType,
20
+ getCacheSignal = _require.getCacheSignal;
21
+
22
+ var invariant = require('invariant');
23
+
24
+ var _require2 = require('relay-runtime'),
25
+ fetchQueryInternal = _require2.__internal.fetchQuery;
26
+
27
+ var warning = require("fbjs/lib/warning");
28
+
29
+ var DEFAULT_FETCH_POLICY = 'store-or-network';
30
+
31
+ function createQueryCache() {
32
+ return new Map();
33
+ }
34
+
35
+ function getQueryCacheKey(operation, fetchPolicy, renderPolicy) {
36
+ var cacheIdentifier = "".concat(fetchPolicy, "-").concat(renderPolicy, "-").concat(operation.request.identifier);
37
+ return cacheIdentifier;
38
+ }
39
+
40
+ function constructQueryResult(operation) {
41
+ var rootFragmentRef = {
42
+ __id: operation.fragment.dataID,
43
+ __fragments: (0, _defineProperty2["default"])({}, operation.fragment.node.name, operation.request.variables),
44
+ __fragmentOwner: operation.request
45
+ };
46
+ return {
47
+ fragmentNode: operation.request.node.fragment,
48
+ fragmentRef: rootFragmentRef
49
+ };
50
+ }
51
+
52
+ function getQueryResultOrFetchQuery_REACT_CACHE(environment, queryOperationDescriptor) {
53
+ var fetchPolicy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULT_FETCH_POLICY;
54
+ var maybeRenderPolicy = arguments.length > 3 ? arguments[3] : undefined;
55
+ var renderPolicy = maybeRenderPolicy !== null && maybeRenderPolicy !== void 0 ? maybeRenderPolicy : environment.UNSTABLE_getDefaultRenderPolicy();
56
+ var cache = getCacheForType(createQueryCache);
57
+ var cacheKey = getQueryCacheKey(queryOperationDescriptor, fetchPolicy, renderPolicy);
58
+ var entry = cache.get(cacheKey);
59
+
60
+ if (entry === undefined) {
61
+ // Initiate a query to fetch the data if needed:
62
+ entry = onCacheMiss(environment, queryOperationDescriptor, fetchPolicy, renderPolicy, function (newCacheEntry) {
63
+ cache.set(cacheKey, newCacheEntry);
64
+ });
65
+ cache.set(cacheKey, entry); // Since this is the first time rendering, retain the query. React will
66
+ // trigger the abort signal when this cache entry is no longer needed.
67
+
68
+ var retention = environment.retain(queryOperationDescriptor);
69
+ var abortSignal = getCacheSignal();
70
+ abortSignal.addEventListener('abort', function () {
71
+ retention.dispose();
72
+ cache["delete"](cacheKey);
73
+ }, {
74
+ once: true
75
+ });
76
+ }
77
+
78
+ switch (entry.status) {
79
+ case 'pending':
80
+ throw entry.promise;
81
+
82
+ case 'rejected':
83
+ throw entry.error;
84
+
85
+ case 'resolved':
86
+ return entry.result;
87
+ }
88
+
89
+ !false ? process.env.NODE_ENV !== "production" ? invariant(false, 'switch statement should be exhaustive') : invariant(false) : void 0;
90
+ }
91
+
92
+ function onCacheMiss(environment, operation, fetchPolicy, renderPolicy, updateCache) {
93
+ // NB: Besides checking if the data is available, calling `check` will write missing
94
+ // data to the store using any missing data handlers specified in the environment.
95
+ var queryAvailability = environment.check(operation);
96
+ var queryStatus = queryAvailability.status;
97
+ var hasFullQuery = queryStatus === 'available';
98
+ var canPartialRender = hasFullQuery || renderPolicy === 'partial' && queryStatus !== 'stale';
99
+ var shouldFetch;
100
+ var shouldRenderNow;
101
+
102
+ switch (fetchPolicy) {
103
+ case 'store-only':
104
+ {
105
+ shouldFetch = false;
106
+ shouldRenderNow = true;
107
+ break;
108
+ }
109
+
110
+ case 'store-or-network':
111
+ {
112
+ shouldFetch = !hasFullQuery;
113
+ shouldRenderNow = canPartialRender;
114
+ break;
115
+ }
116
+
117
+ case 'store-and-network':
118
+ {
119
+ shouldFetch = true;
120
+ shouldRenderNow = canPartialRender;
121
+ break;
122
+ }
123
+
124
+ case 'network-only':
125
+ default:
126
+ {
127
+ shouldFetch = true;
128
+ shouldRenderNow = false;
129
+ break;
130
+ }
131
+ }
132
+
133
+ var promise = shouldFetch ? executeOperationAndKeepUpToDate(environment, operation, updateCache) : undefined;
134
+
135
+ if (shouldRenderNow) {
136
+ return {
137
+ status: 'resolved',
138
+ result: constructQueryResult(operation)
139
+ };
140
+ } else {
141
+ !promise ? process.env.NODE_ENV !== "production" ? invariant(false, 'Should either fetch or render (or both), otherwise we would suspend forever.') : invariant(false) : void 0;
142
+ return {
143
+ status: 'pending',
144
+ promise: promise
145
+ };
146
+ }
147
+ }
148
+
149
+ function executeOperationAndKeepUpToDate(environment, operation, updateCache) {
150
+ var resolvePromise;
151
+ var promise = new Promise(function (r) {
152
+ resolvePromise = r;
153
+ }); // $FlowExpectedError[prop-missing] Expando to annotate Promises.
154
+
155
+ promise.displayName = 'Relay(' + operation.request.node.operation.name + ')';
156
+ var isFirstPayload = true; // FIXME We may still need to cancel network requests for live queries.
157
+
158
+ var fetchObservable = fetchQueryInternal(environment, operation);
159
+ fetchObservable.subscribe({
160
+ start: function start(subscription) {},
161
+ error: function error(_error) {
162
+ if (isFirstPayload) {
163
+ updateCache({
164
+ status: 'rejected',
165
+ error: _error
166
+ });
167
+ } else {
168
+ // TODO:T92030819 Remove this warning and actually throw the network error
169
+ // To complete this task we need to have a way of precisely tracking suspendable points
170
+ process.env.NODE_ENV !== "production" ? warning(false, 'getQueryResultOrFetchQuery: An incremental payload for query `%` returned an error: `%`:`%`.', operation.request.node.operation.name, _error.message, _error.stack) : void 0;
171
+ }
172
+
173
+ resolvePromise();
174
+ isFirstPayload = false;
175
+ },
176
+ next: function next(response) {
177
+ // Stop suspending on the first payload because of streaming, defer, etc.
178
+ updateCache({
179
+ status: 'resolved',
180
+ result: constructQueryResult(operation)
181
+ });
182
+ resolvePromise();
183
+ isFirstPayload = false;
184
+ },
185
+ complete: function complete() {
186
+ updateCache({
187
+ status: 'resolved',
188
+ result: constructQueryResult(operation)
189
+ });
190
+ resolvePromise();
191
+ isFirstPayload = false;
192
+ }
193
+ });
194
+ return promise;
195
+ }
196
+
197
+ module.exports = getQueryResultOrFetchQuery_REACT_CACHE;
@@ -0,0 +1,395 @@
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
+ function isMissingData(state) {
45
+ if (state.kind === 'bailout') {
46
+ return false;
47
+ } else if (state.kind === 'singular') {
48
+ return state.snapshot.isMissingData;
49
+ } else {
50
+ return state.snapshots.some(function (s) {
51
+ return s.isMissingData;
52
+ });
53
+ }
54
+ }
55
+
56
+ function getMissingClientEdges(state) {
57
+ if (state.kind === 'bailout') {
58
+ return null;
59
+ } else if (state.kind === 'singular') {
60
+ var _state$snapshot$missi;
61
+
62
+ return (_state$snapshot$missi = state.snapshot.missingClientEdges) !== null && _state$snapshot$missi !== void 0 ? _state$snapshot$missi : null;
63
+ } else {
64
+ var edges = null;
65
+
66
+ var _iterator = (0, _createForOfIteratorHelper2["default"])(state.snapshots),
67
+ _step;
68
+
69
+ try {
70
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
71
+ var snapshot = _step.value;
72
+
73
+ if (snapshot.missingClientEdges) {
74
+ var _edges;
75
+
76
+ edges = (_edges = edges) !== null && _edges !== void 0 ? _edges : [];
77
+
78
+ var _iterator2 = (0, _createForOfIteratorHelper2["default"])(snapshot.missingClientEdges),
79
+ _step2;
80
+
81
+ try {
82
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
83
+ var edge = _step2.value;
84
+ edges.push(edge);
85
+ }
86
+ } catch (err) {
87
+ _iterator2.e(err);
88
+ } finally {
89
+ _iterator2.f();
90
+ }
91
+ }
92
+ }
93
+ } catch (err) {
94
+ _iterator.e(err);
95
+ } finally {
96
+ _iterator.f();
97
+ }
98
+
99
+ return edges;
100
+ }
101
+ }
102
+
103
+ function handlePotentialSnapshotErrorsForState(environment, state) {
104
+ if (state.kind === 'singular') {
105
+ handlePotentialSnapshotErrors(environment, state.snapshot.missingRequiredFields, state.snapshot.relayResolverErrors);
106
+ } else if (state.kind === 'plural') {
107
+ var _iterator3 = (0, _createForOfIteratorHelper2["default"])(state.snapshots),
108
+ _step3;
109
+
110
+ try {
111
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
112
+ var snapshot = _step3.value;
113
+ handlePotentialSnapshotErrors(environment, snapshot.missingRequiredFields, snapshot.relayResolverErrors);
114
+ }
115
+ } catch (err) {
116
+ _iterator3.e(err);
117
+ } finally {
118
+ _iterator3.f();
119
+ }
120
+ }
121
+ }
122
+
123
+ function handleMissedUpdates(environment, state, setState) {
124
+ if (state.kind === 'bailout') {
125
+ return;
126
+ }
127
+
128
+ var currentEpoch = environment.getStore().getEpoch();
129
+
130
+ if (currentEpoch === state.epoch) {
131
+ return;
132
+ } // The store has updated since we rendered (without us being subscribed yet),
133
+ // so check for any updates to the data we're rendering:
134
+
135
+
136
+ if (state.kind === 'singular') {
137
+ var currentSnapshot = environment.lookup(state.snapshot.selector);
138
+ var updatedData = recycleNodesInto(state.snapshot.data, currentSnapshot.data);
139
+
140
+ if (updatedData !== state.snapshot.data) {
141
+ setState({
142
+ kind: 'singular',
143
+ snapshot: currentSnapshot,
144
+ epoch: currentEpoch
145
+ });
146
+ }
147
+ } else {
148
+ var updates = null;
149
+
150
+ for (var index = 0; index < state.snapshots.length; index++) {
151
+ var snapshot = state.snapshots[index];
152
+
153
+ var _currentSnapshot = environment.lookup(snapshot.selector);
154
+
155
+ var _updatedData = recycleNodesInto(snapshot.data, _currentSnapshot.data);
156
+
157
+ if (_updatedData !== snapshot.data) {
158
+ updates = updates === null ? new Array(state.snapshots.length) : updates;
159
+ updates[index] = snapshot;
160
+ }
161
+ }
162
+
163
+ if (updates !== null) {
164
+ var theUpdates = updates; // preserve flow refinement.
165
+
166
+ setState(function (existing) {
167
+ !(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;
168
+ var updated = (0, _toConsumableArray2["default"])(existing.snapshots);
169
+
170
+ for (var _index = 0; _index < theUpdates.length; _index++) {
171
+ var updatedSnapshot = theUpdates[_index];
172
+
173
+ if (updatedSnapshot) {
174
+ updated[_index] = updatedSnapshot;
175
+ }
176
+ }
177
+
178
+ return {
179
+ kind: 'plural',
180
+ snapshots: updated,
181
+ epoch: currentEpoch
182
+ };
183
+ });
184
+ }
185
+ }
186
+ }
187
+
188
+ function handleMissingClientEdge(environment, parentFragmentNode, parentFragmentRef, missingClientEdgeRequestInfo, queryOptions) {
189
+ var originalVariables = getVariablesFromFragment(parentFragmentNode, parentFragmentRef);
190
+ var variables = (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, originalVariables), {}, {
191
+ id: missingClientEdgeRequestInfo.clientEdgeDestinationID // TODO should be a reserved name
192
+
193
+ });
194
+ 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
195
+ // doing here is started the query if needed and retaining and releasing it
196
+ // according to the component mount/suspense cycle; getQueryResultOrFetchQuery
197
+ // already handles this by itself.
198
+
199
+ getQueryResultOrFetchQuery(environment, queryOperationDescriptor, queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.fetchPolicy);
200
+ }
201
+
202
+ function subscribeToSnapshot(environment, state, setState) {
203
+ if (state.kind === 'bailout') {
204
+ return function () {};
205
+ } else if (state.kind === 'singular') {
206
+ var disposable = environment.subscribe(state.snapshot, function (latestSnapshot) {
207
+ setState({
208
+ kind: 'singular',
209
+ snapshot: latestSnapshot,
210
+ epoch: environment.getStore().getEpoch()
211
+ });
212
+ });
213
+ return function () {
214
+ disposable.dispose();
215
+ };
216
+ } else {
217
+ var disposables = state.snapshots.map(function (snapshot, index) {
218
+ return environment.subscribe(snapshot, function (latestSnapshot) {
219
+ setState(function (existing) {
220
+ !(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;
221
+ var updated = (0, _toConsumableArray2["default"])(existing.snapshots);
222
+ updated[index] = latestSnapshot;
223
+ return {
224
+ kind: 'plural',
225
+ snapshots: updated,
226
+ epoch: environment.getStore().getEpoch()
227
+ };
228
+ });
229
+ });
230
+ });
231
+ return function () {
232
+ var _iterator4 = (0, _createForOfIteratorHelper2["default"])(disposables),
233
+ _step4;
234
+
235
+ try {
236
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
237
+ var d = _step4.value;
238
+ d.dispose();
239
+ }
240
+ } catch (err) {
241
+ _iterator4.e(err);
242
+ } finally {
243
+ _iterator4.f();
244
+ }
245
+ };
246
+ }
247
+ }
248
+
249
+ function getFragmentState(environment, fragmentSelector) {
250
+ if (fragmentSelector == null) {
251
+ return {
252
+ kind: 'bailout'
253
+ };
254
+ } else if (fragmentSelector.kind === 'PluralReaderSelector') {
255
+ return {
256
+ kind: 'plural',
257
+ snapshots: fragmentSelector.selectors.map(function (s) {
258
+ return environment.lookup(s);
259
+ }),
260
+ epoch: environment.getStore().getEpoch()
261
+ };
262
+ } else {
263
+ return {
264
+ kind: 'singular',
265
+ snapshot: environment.lookup(fragmentSelector),
266
+ epoch: environment.getStore().getEpoch()
267
+ };
268
+ }
269
+ } // fragmentNode cannot change during the lifetime of the component, though fragmentRef may change.
270
+
271
+
272
+ function useFragmentInternal_REACT_CACHE(fragmentNode, fragmentRef, hookDisplayName, queryOptions, fragmentKey) {
273
+ var _fragmentNode$metadat;
274
+
275
+ var fragmentSelector = getSelector(fragmentNode, fragmentRef);
276
+
277
+ if ((fragmentNode === null || fragmentNode === void 0 ? void 0 : (_fragmentNode$metadat = fragmentNode.metadata) === null || _fragmentNode$metadat === void 0 ? void 0 : _fragmentNode$metadat.plural) === true) {
278
+ !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;
279
+ } else {
280
+ !!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;
281
+ }
282
+
283
+ !(fragmentRef == null || 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;
284
+ var environment = useRelayEnvironment();
285
+
286
+ var _useState = useState(function () {
287
+ return getFragmentState(environment, fragmentSelector);
288
+ }),
289
+ rawState = _useState[0],
290
+ setState = _useState[1];
291
+
292
+ var _useState2 = useState(fragmentSelector),
293
+ previousFragmentSelector = _useState2[0],
294
+ setPreviousFragmentSelector = _useState2[1];
295
+
296
+ if (!areEqualSelectors(fragmentSelector, previousFragmentSelector)) {
297
+ setPreviousFragmentSelector(fragmentSelector);
298
+ setState(getFragmentState(environment, fragmentSelector));
299
+ }
300
+
301
+ var state;
302
+
303
+ if (fragmentRef == null) {
304
+ state = {
305
+ kind: 'bailout'
306
+ };
307
+ } else if (rawState.kind === 'plural' && rawState.snapshots.length === 0) {
308
+ state = {
309
+ kind: 'bailout'
310
+ };
311
+ } else {
312
+ state = rawState;
313
+ } // Handle the queries for any missing client edges; this may suspend.
314
+ // FIXME handle client edges in parallel.
315
+
316
+
317
+ var missingClientEdges = getMissingClientEdges(state);
318
+
319
+ if (missingClientEdges === null || missingClientEdges === void 0 ? void 0 : missingClientEdges.length) {
320
+ var _iterator5 = (0, _createForOfIteratorHelper2["default"])(missingClientEdges),
321
+ _step5;
322
+
323
+ try {
324
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
325
+ var edge = _step5.value;
326
+ handleMissingClientEdge(environment, fragmentNode, fragmentRef, edge, queryOptions);
327
+ }
328
+ } catch (err) {
329
+ _iterator5.e(err);
330
+ } finally {
331
+ _iterator5.f();
332
+ }
333
+ }
334
+
335
+ if (isMissingData(state)) {
336
+ // Suspend if an active operation bears on this fragment, either the
337
+ // fragment's owner or some other mutation etc. that could affect it:
338
+ !(fragmentSelector != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'refinement, see invariants above') : invariant(false) : void 0;
339
+ var fragmentOwner = fragmentSelector.kind === 'PluralReaderSelector' ? fragmentSelector.selectors[0].owner : fragmentSelector.owner;
340
+ var pendingOperationsResult = getPendingOperationsForFragment(environment, fragmentNode, fragmentOwner);
341
+
342
+ if (pendingOperationsResult) {
343
+ throw pendingOperationsResult.promise;
344
+ } // Report required fields only if we're not suspending, since that means
345
+ // they're missing even though we are out of options for possibly fetching them:
346
+
347
+
348
+ handlePotentialSnapshotErrorsForState(environment, state);
349
+ } // Subscriptions:
350
+
351
+
352
+ var isMountedRef = useRef(false);
353
+ var isListeningForUpdatesRef = useRef(true);
354
+
355
+ function enableStoreUpdates() {
356
+ isListeningForUpdatesRef.current = true;
357
+ handleMissedUpdates(environment, state, setState);
358
+ }
359
+
360
+ function disableStoreUpdates() {
361
+ isListeningForUpdatesRef.current = false;
362
+ }
363
+
364
+ useEffect(function () {
365
+ var wasAlreadySubscribed = isMountedRef.current;
366
+ isMountedRef.current = true;
367
+
368
+ if (!wasAlreadySubscribed) {
369
+ handleMissedUpdates(environment, state, setState);
370
+ }
371
+
372
+ return subscribeToSnapshot(environment, state, setState);
373
+ }, [environment, state]);
374
+ var data = useMemo(function () {
375
+ return state.kind === 'bailout' ? {} : state.kind === 'singular' ? state.snapshot.data : state.snapshots.map(function (s) {
376
+ return s.data;
377
+ });
378
+ }, [state]);
379
+
380
+ if (process.env.NODE_ENV !== "production") {
381
+ // eslint-disable-next-line react-hooks/rules-of-hooks
382
+ useDebugValue({
383
+ fragment: fragmentNode.name,
384
+ data: data
385
+ });
386
+ }
387
+
388
+ return {
389
+ data: data,
390
+ disableStoreUpdates: disableStoreUpdates,
391
+ enableStoreUpdates: enableStoreUpdates
392
+ };
393
+ }
394
+
395
+ module.exports = useFragmentInternal_REACT_CACHE;
@@ -0,0 +1,45 @@
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
+ function useLazyLoadQuery_REACT_CACHE(gqlQuery, variables, options) {
26
+ var _options$networkCache;
27
+
28
+ useTrackLoadQueryInRender();
29
+ var environment = useRelayEnvironment();
30
+ var queryOperationDescriptor = useMemoOperationDescriptor(gqlQuery, variables, (_options$networkCache = options === null || options === void 0 ? void 0 : options.networkCacheConfig) !== null && _options$networkCache !== void 0 ? _options$networkCache : {
31
+ force: true
32
+ }); // Get the query going if needed -- this may suspend.
33
+
34
+ var queryResult = getQueryResultOrFetchQuery(environment, queryOperationDescriptor, options === null || options === void 0 ? void 0 : options.fetchPolicy); // Read the query's root fragment -- this may suspend.
35
+
36
+ var fragmentNode = queryResult.fragmentNode,
37
+ fragmentRef = queryResult.fragmentRef; // $FlowExpectedError[incompatible-return] Is this a fixable incompatible-return?
38
+
39
+ return useFragmentInternal(fragmentNode, fragmentRef, 'useLazyLoadQuery()', {
40
+ fetchPolicy: options === null || options === void 0 ? void 0 : options.fetchPolicy,
41
+ networkCacheConfig: options === null || options === void 0 ? void 0 : options.networkCacheConfig
42
+ }).data;
43
+ }
44
+
45
+ module.exports = useLazyLoadQuery_REACT_CACHE;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "react-relay",
3
3
  "description": "A framework for building GraphQL-driven React applications.",
4
- "version": "13.1.1",
4
+ "version": "13.2.0",
5
5
  "keywords": [
6
6
  "graphql",
7
7
  "relay",
@@ -20,10 +20,10 @@
20
20
  "fbjs": "^3.0.2",
21
21
  "invariant": "^2.2.4",
22
22
  "nullthrows": "^1.1.1",
23
- "relay-runtime": "13.1.1"
23
+ "relay-runtime": "13.2.0"
24
24
  },
25
25
  "peerDependencies": {
26
- "react": "^16.9.0 || ^17"
26
+ "react": "^16.9.0 || ^17 || ^18"
27
27
  },
28
28
  "directories": {
29
29
  "": "./"