react-relay 13.2.0 → 14.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ReactRelayContext.js +1 -1
- package/ReactRelayFragmentContainer.js.flow +7 -4
- package/ReactRelayPaginationContainer.js.flow +13 -8
- package/ReactRelayQueryFetcher.js.flow +1 -0
- package/ReactRelayQueryRenderer.js.flow +6 -2
- package/ReactRelayRefetchContainer.js.flow +10 -3
- package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer.graphql.js.flow +2 -2
- package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer2.graphql.js.flow +2 -2
- package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtestQuery.graphql.js.flow +3 -3
- package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtest_viewer.graphql.js.flow +3 -3
- package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtestQuery.graphql.js.flow +3 -3
- package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtest_viewer.graphql.js.flow +3 -3
- package/__flowtests__/__generated__/RelayModernFlowtest_badref.graphql.js.flow +2 -2
- package/__flowtests__/__generated__/RelayModernFlowtest_notref.graphql.js.flow +2 -2
- package/__flowtests__/__generated__/RelayModernFlowtest_user.graphql.js.flow +2 -2
- package/__flowtests__/__generated__/RelayModernFlowtest_users.graphql.js.flow +2 -2
- package/buildReactRelayContainer.js.flow +2 -2
- package/hooks.js +1 -1
- package/index.js +1 -1
- package/legacy.js +1 -1
- package/lib/ReactRelayQueryFetcher.js +1 -0
- package/lib/ReactRelayQueryRenderer.js +0 -1
- package/lib/readContext.js +2 -1
- package/lib/relay-hooks/FragmentResource.js +52 -10
- package/lib/relay-hooks/HooksImplementation.js +29 -0
- package/lib/relay-hooks/MatchContainer.js +1 -0
- package/lib/relay-hooks/QueryResource.js +2 -1
- package/lib/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js +203 -56
- package/lib/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js +254 -109
- package/lib/relay-hooks/react-cache/useFragment_REACT_CACHE.js +51 -0
- package/lib/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js +13 -2
- package/lib/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js +125 -0
- package/lib/relay-hooks/useFragment.js +15 -1
- package/lib/relay-hooks/useLazyLoadQuery.js +18 -2
- package/lib/relay-hooks/useMutation.js +4 -5
- package/lib/relay-hooks/usePreloadedQuery.js +18 -2
- package/package.json +2 -2
- package/react-relay-hooks.js +2 -2
- package/react-relay-hooks.min.js +2 -2
- package/react-relay-legacy.js +2 -2
- package/react-relay-legacy.min.js +2 -2
- package/react-relay.js +2 -2
- package/react-relay.min.js +2 -2
- package/readContext.js.flow +1 -0
- package/relay-hooks/FragmentResource.js.flow +55 -9
- package/relay-hooks/HooksImplementation.js.flow +45 -0
- package/relay-hooks/MatchContainer.js.flow +8 -1
- package/relay-hooks/QueryResource.js.flow +4 -2
- package/relay-hooks/__flowtests__/__generated__/useFragmentFlowtest_user.graphql.js.flow +2 -2
- package/relay-hooks/__flowtests__/__generated__/useFragmentFlowtest_users.graphql.js.flow +2 -2
- package/relay-hooks/loadQuery.js.flow +2 -1
- package/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js.flow +245 -64
- package/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js.flow +242 -99
- package/relay-hooks/react-cache/useFragment_REACT_CACHE.js.flow +74 -0
- package/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js.flow +10 -4
- package/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js.flow +153 -0
- package/relay-hooks/useFragment.js.flow +17 -10
- package/relay-hooks/useLazyLoadQuery.js.flow +38 -3
- package/relay-hooks/useMutation.js.flow +3 -3
- package/relay-hooks/usePreloadedQuery.js.flow +30 -2
- package/relay-hooks/useRefetchableFragmentNode.js.flow +26 -11
- package/relay-hooks/useSubscription.js.flow +14 -8
@@ -41,6 +41,8 @@ var _require2 = require('relay-runtime'),
|
|
41
41
|
handlePotentialSnapshotErrors = _require2.handlePotentialSnapshotErrors,
|
42
42
|
recycleNodesInto = _require2.recycleNodesInto;
|
43
43
|
|
44
|
+
var warning = require("fbjs/lib/warning");
|
45
|
+
|
44
46
|
function isMissingData(state) {
|
45
47
|
if (state.kind === 'bailout') {
|
46
48
|
return false;
|
@@ -119,16 +121,22 @@ function handlePotentialSnapshotErrorsForState(environment, state) {
|
|
119
121
|
}
|
120
122
|
}
|
121
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
|
+
*/
|
122
128
|
|
123
|
-
|
129
|
+
|
130
|
+
function handleMissedUpdates(environment, state) {
|
124
131
|
if (state.kind === 'bailout') {
|
125
|
-
return;
|
126
|
-
}
|
132
|
+
return null;
|
133
|
+
} // FIXME this is invalid if we've just switched environments.
|
134
|
+
|
127
135
|
|
128
136
|
var currentEpoch = environment.getStore().getEpoch();
|
129
137
|
|
130
138
|
if (currentEpoch === state.epoch) {
|
131
|
-
return;
|
139
|
+
return null;
|
132
140
|
} // The store has updated since we rendered (without us being subscribed yet),
|
133
141
|
// so check for any updates to the data we're rendering:
|
134
142
|
|
@@ -136,16 +144,24 @@ function handleMissedUpdates(environment, state, setState) {
|
|
136
144
|
if (state.kind === 'singular') {
|
137
145
|
var currentSnapshot = environment.lookup(state.snapshot.selector);
|
138
146
|
var updatedData = recycleNodesInto(state.snapshot.data, currentSnapshot.data);
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
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
|
+
}];
|
147
162
|
} else {
|
148
|
-
var
|
163
|
+
var didMissUpdates = false;
|
164
|
+
var currentSnapshots = [];
|
149
165
|
|
150
166
|
for (var index = 0; index < state.snapshots.length; index++) {
|
151
167
|
var snapshot = state.snapshots[index];
|
@@ -154,34 +170,30 @@ function handleMissedUpdates(environment, state, setState) {
|
|
154
170
|
|
155
171
|
var _updatedData = recycleNodesInto(snapshot.data, _currentSnapshot.data);
|
156
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
|
+
|
157
184
|
if (_updatedData !== snapshot.data) {
|
158
|
-
|
159
|
-
updates[index] = snapshot;
|
185
|
+
didMissUpdates = true;
|
160
186
|
}
|
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
187
|
|
170
|
-
|
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
|
-
});
|
188
|
+
currentSnapshots.push(_updatedCurrentSnapshot);
|
184
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
|
+
}];
|
185
197
|
}
|
186
198
|
}
|
187
199
|
|
@@ -196,7 +208,13 @@ function handleMissingClientEdge(environment, parentFragmentNode, parentFragment
|
|
196
208
|
// according to the component mount/suspense cycle; getQueryResultOrFetchQuery
|
197
209
|
// already handles this by itself.
|
198
210
|
|
199
|
-
getQueryResultOrFetchQuery(environment, queryOperationDescriptor,
|
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;
|
200
218
|
}
|
201
219
|
|
202
220
|
function subscribeToSnapshot(environment, state, setState) {
|
@@ -204,10 +222,12 @@ function subscribeToSnapshot(environment, state, setState) {
|
|
204
222
|
return function () {};
|
205
223
|
} else if (state.kind === 'singular') {
|
206
224
|
var disposable = environment.subscribe(state.snapshot, function (latestSnapshot) {
|
207
|
-
setState({
|
208
|
-
|
209
|
-
|
210
|
-
|
225
|
+
setState(function (_) {
|
226
|
+
return {
|
227
|
+
kind: 'singular',
|
228
|
+
snapshot: latestSnapshot,
|
229
|
+
epoch: environment.getStore().getEpoch()
|
230
|
+
};
|
211
231
|
});
|
212
232
|
});
|
213
233
|
return function () {
|
@@ -246,7 +266,7 @@ function subscribeToSnapshot(environment, state, setState) {
|
|
246
266
|
}
|
247
267
|
}
|
248
268
|
|
249
|
-
function getFragmentState(environment, fragmentSelector) {
|
269
|
+
function getFragmentState(environment, fragmentSelector, isPlural) {
|
250
270
|
if (fragmentSelector == null) {
|
251
271
|
return {
|
252
272
|
kind: 'bailout'
|
@@ -270,66 +290,148 @@ function getFragmentState(environment, fragmentSelector) {
|
|
270
290
|
|
271
291
|
|
272
292
|
function useFragmentInternal_REACT_CACHE(fragmentNode, fragmentRef, hookDisplayName, queryOptions, fragmentKey) {
|
273
|
-
var _fragmentNode$metadat;
|
293
|
+
var _fragmentNode$metadat, _fragmentNode$metadat2;
|
274
294
|
|
275
|
-
var fragmentSelector =
|
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;
|
276
299
|
|
277
|
-
if (
|
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;
|
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;
|
279
302
|
} else {
|
280
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;
|
281
304
|
}
|
282
305
|
|
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;
|
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;
|
284
307
|
var environment = useRelayEnvironment();
|
285
308
|
|
286
309
|
var _useState = useState(function () {
|
287
|
-
return getFragmentState(environment, fragmentSelector);
|
310
|
+
return getFragmentState(environment, fragmentSelector, isPlural);
|
288
311
|
}),
|
289
312
|
rawState = _useState[0],
|
290
|
-
setState = _useState[1];
|
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
|
+
};
|
291
331
|
|
292
|
-
var
|
293
|
-
|
294
|
-
|
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.
|
295
335
|
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
}
|
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.
|
300
339
|
|
301
|
-
var state;
|
302
340
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
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;
|
313
364
|
} // Handle the queries for any missing client edges; this may suspend.
|
314
365
|
// FIXME handle client edges in parallel.
|
315
366
|
|
316
367
|
|
317
|
-
|
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
|
318
375
|
|
319
|
-
|
320
|
-
var _iterator5 = (0, _createForOfIteratorHelper2["default"])(missingClientEdges),
|
321
|
-
_step5;
|
376
|
+
var effects;
|
322
377
|
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
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
|
+
}
|
327
394
|
}
|
328
|
-
|
329
|
-
|
330
|
-
}
|
331
|
-
|
332
|
-
|
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]);
|
333
435
|
}
|
334
436
|
|
335
437
|
if (isMissingData(state)) {
|
@@ -346,36 +448,83 @@ function useFragmentInternal_REACT_CACHE(fragmentNode, fragmentRef, hookDisplayN
|
|
346
448
|
|
347
449
|
|
348
450
|
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
451
|
}
|
363
452
|
|
364
453
|
useEffect(function () {
|
365
|
-
|
366
|
-
|
454
|
+
// Check for updates since the state was rendered
|
455
|
+
var currentState = subscribedState;
|
456
|
+
var updates = handleMissedUpdates(environment, subscribedState);
|
367
457
|
|
368
|
-
if (
|
369
|
-
|
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;
|
370
473
|
}
|
371
474
|
|
372
|
-
return subscribeToSnapshot(environment,
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
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
|
+
});
|
377
491
|
});
|
378
|
-
}, [
|
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
|
+
}
|
379
528
|
|
380
529
|
if (process.env.NODE_ENV !== "production") {
|
381
530
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
@@ -385,11 +534,7 @@ function useFragmentInternal_REACT_CACHE(fragmentNode, fragmentRef, hookDisplayN
|
|
385
534
|
});
|
386
535
|
}
|
387
536
|
|
388
|
-
return
|
389
|
-
data: data,
|
390
|
-
disableStoreUpdates: disableStoreUpdates,
|
391
|
-
enableStoreUpdates: enableStoreUpdates
|
392
|
-
};
|
537
|
+
return data;
|
393
538
|
}
|
394
539
|
|
395
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;
|
@@ -22,6 +22,9 @@ var getQueryResultOrFetchQuery = require('./getQueryResultOrFetchQuery_REACT_CAC
|
|
22
22
|
|
23
23
|
var useFragmentInternal = require('./useFragmentInternal_REACT_CACHE');
|
24
24
|
|
25
|
+
var _require2 = require('react'),
|
26
|
+
useEffect = _require2.useEffect;
|
27
|
+
|
25
28
|
function useLazyLoadQuery_REACT_CACHE(gqlQuery, variables, options) {
|
26
29
|
var _options$networkCache;
|
27
30
|
|
@@ -31,7 +34,15 @@ function useLazyLoadQuery_REACT_CACHE(gqlQuery, variables, options) {
|
|
31
34
|
force: true
|
32
35
|
}); // Get the query going if needed -- this may suspend.
|
33
36
|
|
34
|
-
var
|
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.
|
35
46
|
|
36
47
|
var fragmentNode = queryResult.fragmentNode,
|
37
48
|
fragmentRef = queryResult.fragmentRef; // $FlowExpectedError[incompatible-return] Is this a fixable incompatible-return?
|
@@ -39,7 +50,7 @@ function useLazyLoadQuery_REACT_CACHE(gqlQuery, variables, options) {
|
|
39
50
|
return useFragmentInternal(fragmentNode, fragmentRef, 'useLazyLoadQuery()', {
|
40
51
|
fetchPolicy: options === null || options === void 0 ? void 0 : options.fetchPolicy,
|
41
52
|
networkCacheConfig: options === null || options === void 0 ? void 0 : options.networkCacheConfig
|
42
|
-
})
|
53
|
+
});
|
43
54
|
}
|
44
55
|
|
45
56
|
module.exports = useLazyLoadQuery_REACT_CACHE;
|