react-relay 16.0.0 → 16.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. package/ReactRelayContext.js +1 -1
  2. package/hooks.js +1 -1
  3. package/index.js +1 -1
  4. package/legacy.js +1 -1
  5. package/lib/relay-hooks/HooksImplementation.js +1 -1
  6. package/lib/relay-hooks/{react-cache/readFragmentInternal_REACT_CACHE.js → experimental/readFragmentInternal_EXPERIMENTAL.js} +2 -2
  7. package/lib/relay-hooks/{react-cache/useFragmentInternal_REACT_CACHE.js → experimental/useFragmentInternal_EXPERIMENTAL.js} +2 -2
  8. package/lib/relay-hooks/{react-cache/useFragment_REACT_CACHE.js → experimental/useFragment_EXPERIMENTAL.js} +1 -1
  9. package/lib/relay-hooks/{react-cache/usePaginationFragment_REACT_CACHE.js → experimental/usePaginationFragment_EXPERIMENTAL.js} +1 -1
  10. package/lib/relay-hooks/{react-cache/useRefetchableFragmentInternal_REACT_CACHE.js → experimental/useRefetchableFragmentInternal_EXPERIMENTAL.js} +2 -2
  11. package/lib/relay-hooks/{react-cache/useRefetchableFragment_REACT_CACHE.js → experimental/useRefetchableFragment_EXPERIMENTAL.js} +1 -1
  12. package/lib/relay-hooks/useLazyLoadQueryNode.js +12 -2
  13. package/package.json +2 -2
  14. package/react-relay-hooks.js +2 -2
  15. package/react-relay-hooks.min.js +2 -2
  16. package/react-relay-legacy.js +2 -2
  17. package/react-relay-legacy.min.js +2 -2
  18. package/react-relay.js +2 -2
  19. package/react-relay.min.js +2 -2
  20. package/relay-hooks/EntryPointTypes.flow.js.flow +17 -19
  21. package/relay-hooks/HooksImplementation.js.flow +3 -1
  22. package/relay-hooks/{react-cache/readFragmentInternal_REACT_CACHE.js.flow → experimental/readFragmentInternal_EXPERIMENTAL.js.flow} +2 -2
  23. package/relay-hooks/{react-cache/useFragmentInternal_REACT_CACHE.js.flow → experimental/useFragmentInternal_EXPERIMENTAL.js.flow} +4 -4
  24. package/relay-hooks/{react-cache/useFragment_REACT_CACHE.js.flow → experimental/useFragment_EXPERIMENTAL.js.flow} +1 -1
  25. package/relay-hooks/{react-cache/usePaginationFragment_REACT_CACHE.js.flow → experimental/usePaginationFragment_EXPERIMENTAL.js.flow} +2 -2
  26. package/relay-hooks/{react-cache/useRefetchableFragmentInternal_REACT_CACHE.js.flow → experimental/useRefetchableFragmentInternal_EXPERIMENTAL.js.flow} +11 -11
  27. package/relay-hooks/{react-cache/useRefetchableFragment_REACT_CACHE.js.flow → experimental/useRefetchableFragment_EXPERIMENTAL.js.flow} +1 -1
  28. package/relay-hooks/useBlockingPaginationFragment.js.flow +9 -14
  29. package/relay-hooks/useLazyLoadQueryNode.js.flow +17 -1
  30. package/relay-hooks/usePaginationFragment.js.flow +5 -7
  31. package/relay-hooks/useRefetchableFragment.js.flow +13 -16
  32. package/relay-hooks/useRefetchableFragmentNode.js.flow +5 -7
  33. package/lib/relay-hooks/react-cache/RelayReactCache.js +0 -20
  34. package/lib/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js +0 -255
  35. package/lib/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js +0 -33
  36. package/lib/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js +0 -81
  37. package/relay-hooks/react-cache/RelayReactCache.js.flow +0 -40
  38. package/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js.flow +0 -430
  39. package/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js.flow +0 -70
  40. package/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js.flow +0 -150
@@ -1,430 +0,0 @@
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
- * @flow strict-local
8
- * @format
9
- * @oncall relay
10
- */
11
-
12
- 'use strict';
13
-
14
- import type {
15
- FetchPolicy,
16
- GraphQLResponse,
17
- IEnvironment,
18
- Observable,
19
- OperationDescriptor,
20
- ReaderFragment,
21
- RenderPolicy,
22
- } from 'relay-runtime';
23
-
24
- const SuspenseResource = require('../SuspenseResource');
25
- const {getCacheForType, getCacheSignal} = require('./RelayReactCache');
26
- const invariant = require('invariant');
27
- const {
28
- __internal: {fetchQuery: fetchQueryInternal},
29
- RelayFeatureFlags,
30
- } = require('relay-runtime');
31
- const warning = require('warning');
32
-
33
- type QueryCacheCommitable = () => () => void;
34
-
35
- type QueryResult = {
36
- fragmentNode: ReaderFragment,
37
- fragmentRef: mixed,
38
- };
39
-
40
- // Note that the status of a cache entry will be 'resolved' when partial
41
- // rendering is allowed, even if a fetch is ongoing. The pending status
42
- // is specifically to indicate that we should suspend.
43
- // Note also that the retainCount is different from the retain count of
44
- // an operation, which is maintained by the Environment. This retain
45
- // count is used in Legacy Timeouts mode to count how many components
46
- // are mounted that use the entry, plus one count for the temporary retain
47
- // before any components have mounted. It is unused when Legacy Timeouts
48
- // mode is off.
49
- type QueryCacheEntryStatus =
50
- | {
51
- status: 'resolved',
52
- result: QueryResult,
53
- }
54
- | {
55
- status: 'pending',
56
- promise: Promise<void>,
57
- }
58
- | {
59
- status: 'rejected',
60
- error: Error,
61
- };
62
-
63
- type QueryCacheEntry = {
64
- ...QueryCacheEntryStatus,
65
- onCommit: QueryCacheCommitable,
66
- suspenseResource: SuspenseResource | null,
67
- };
68
-
69
- const DEFAULT_FETCH_POLICY = 'store-or-network';
70
-
71
- const WEAKMAP_SUPPORTED = typeof WeakMap === 'function';
72
-
73
- interface IMap<K, V> {
74
- delete(key: K): boolean;
75
- get(key: K): V | void;
76
- set(key: K, value: V): IMap<K, V>;
77
- }
78
-
79
- type QueryCacheKey = string;
80
-
81
- class QueryCache {
82
- _map: IMap<IEnvironment, Map<QueryCacheKey, QueryCacheEntry>>;
83
-
84
- constructor() {
85
- this._map = WEAKMAP_SUPPORTED ? new WeakMap() : new Map();
86
- }
87
-
88
- get(environment: IEnvironment, key: QueryCacheKey): QueryCacheEntry | void {
89
- let forEnv = this._map.get(environment);
90
- if (!forEnv) {
91
- forEnv = new Map();
92
- this._map.set(environment, forEnv);
93
- }
94
- return forEnv.get(key);
95
- }
96
-
97
- set(
98
- environment: IEnvironment,
99
- key: QueryCacheKey,
100
- value: QueryCacheEntry,
101
- ): void {
102
- let forEnv = this._map.get(environment);
103
- if (!forEnv) {
104
- forEnv = new Map();
105
- this._map.set(environment, forEnv);
106
- }
107
- forEnv.set(key, value);
108
- }
109
-
110
- delete(environment: IEnvironment, key: QueryCacheKey): void {
111
- const forEnv = this._map.get(environment);
112
- if (!forEnv) {
113
- return;
114
- }
115
- forEnv.delete(key);
116
- if (forEnv.size === 0) {
117
- this._map.delete(environment);
118
- }
119
- }
120
- }
121
-
122
- function createQueryCache(): QueryCache {
123
- return new QueryCache();
124
- }
125
-
126
- const noopOnCommit = () => {
127
- return () => undefined;
128
- };
129
-
130
- const noopPromise = new Promise<void>(() => {});
131
-
132
- function getQueryCacheKey(
133
- operation: OperationDescriptor,
134
- fetchPolicy: FetchPolicy,
135
- renderPolicy: RenderPolicy,
136
- fetchKey?: ?string | ?number,
137
- ): QueryCacheKey {
138
- return `${fetchPolicy}-${renderPolicy}-${operation.request.identifier}-${
139
- fetchKey ?? ''
140
- }`;
141
- }
142
-
143
- function constructQueryResult(operation: OperationDescriptor): QueryResult {
144
- const rootFragmentRef = {
145
- __id: operation.fragment.dataID,
146
- __fragments: {
147
- [operation.fragment.node.name]: operation.request.variables,
148
- },
149
- __fragmentOwner: operation.request,
150
- };
151
- return {
152
- fragmentNode: operation.request.node.fragment,
153
- fragmentRef: rootFragmentRef,
154
- };
155
- }
156
-
157
- function makeInitialCacheEntry() {
158
- return {
159
- status: 'pending',
160
- promise: noopPromise,
161
- onCommit: noopOnCommit,
162
- suspenseResource: null,
163
- };
164
- }
165
-
166
- function getQueryResultOrFetchQuery_REACT_CACHE(
167
- environment: IEnvironment,
168
- queryOperationDescriptor: OperationDescriptor,
169
- options?: {
170
- fetchPolicy?: FetchPolicy,
171
- renderPolicy?: RenderPolicy,
172
- fetchKey?: ?string | ?number,
173
- fetchObservable?: Observable<GraphQLResponse>,
174
- },
175
- ): [QueryResult, QueryCacheCommitable] {
176
- const fetchPolicy = options?.fetchPolicy ?? DEFAULT_FETCH_POLICY;
177
- const renderPolicy =
178
- options?.renderPolicy ?? environment.UNSTABLE_getDefaultRenderPolicy();
179
-
180
- const cache = getCacheForType(createQueryCache);
181
-
182
- const cacheKey = getQueryCacheKey(
183
- queryOperationDescriptor,
184
- fetchPolicy,
185
- renderPolicy,
186
- options?.fetchKey,
187
- );
188
-
189
- const initialEntry = cache.get(environment, cacheKey);
190
-
191
- function updateCache(
192
- updater: QueryCacheEntryStatus => QueryCacheEntryStatus,
193
- ) {
194
- let currentEntry = cache.get(environment, cacheKey);
195
- if (!currentEntry) {
196
- currentEntry = makeInitialCacheEntry();
197
- cache.set(environment, cacheKey, currentEntry);
198
- }
199
- // $FlowExpectedError[prop-missing] Extra properties are passed in -- this is fine
200
- const newStatus: {...} = updater(currentEntry);
201
- // $FlowExpectedError[cannot-spread-inexact] Flow cannot understand that this is valid...
202
- cache.set(environment, cacheKey, {...currentEntry, ...newStatus});
203
- // ... but we can because QueryCacheEntry spreads QueryCacheEntryStatus, so spreading
204
- // a QueryCacheEntryStatus into a QueryCacheEntry will result in a valid QueryCacheEntry.
205
- }
206
-
207
- // Initiate a query to fetch the data if needed:
208
- if (RelayFeatureFlags.USE_REACT_CACHE_LEGACY_TIMEOUTS) {
209
- let entry;
210
- if (initialEntry === undefined) {
211
- onCacheMiss(
212
- environment,
213
- queryOperationDescriptor,
214
- fetchPolicy,
215
- renderPolicy,
216
- updateCache,
217
- options?.fetchObservable,
218
- );
219
- const createdEntry = cache.get(environment, cacheKey);
220
- invariant(
221
- createdEntry !== undefined,
222
- 'An entry should have been created by onCacheMiss. This is a bug in Relay.',
223
- );
224
- entry = createdEntry;
225
- } else {
226
- entry = initialEntry;
227
- }
228
- if (!entry.suspenseResource) {
229
- entry.suspenseResource = new SuspenseResource(() => {
230
- const retention = environment.retain(queryOperationDescriptor);
231
- return {
232
- dispose: () => {
233
- retention.dispose();
234
- cache.delete(environment, cacheKey);
235
- },
236
- };
237
- });
238
- }
239
- if (entry.onCommit === noopOnCommit) {
240
- entry.onCommit = () => {
241
- invariant(
242
- entry.suspenseResource,
243
- 'SuspenseResource should have been initialized. This is a bug in Relay.',
244
- );
245
- const retention = entry.suspenseResource.permanentRetain(environment);
246
- return () => {
247
- retention.dispose();
248
- };
249
- };
250
- }
251
- entry.suspenseResource.temporaryRetain(environment);
252
- } else {
253
- if (initialEntry === undefined) {
254
- // This is the behavior we eventually want: We retain the query until the
255
- // presiding Cache component unmounts, at which point the AbortSignal
256
- // will be triggered.
257
- onCacheMiss(
258
- environment,
259
- queryOperationDescriptor,
260
- fetchPolicy,
261
- renderPolicy,
262
- updateCache,
263
- options?.fetchObservable,
264
- );
265
-
266
- // Since this is the first time rendering, retain the query. React will
267
- // trigger the abort signal when this cache entry is no longer needed.
268
- const retention = environment.retain(queryOperationDescriptor);
269
-
270
- const dispose = () => {
271
- retention.dispose();
272
- cache.delete(environment, cacheKey);
273
- };
274
- const abortSignal = getCacheSignal();
275
- abortSignal.addEventListener('abort', dispose, {once: true});
276
- }
277
- }
278
-
279
- const entry = cache.get(environment, cacheKey); // could be a different entry now if synchronously resolved
280
- invariant(
281
- entry !== undefined,
282
- 'An entry should have been created by onCacheMiss. This is a bug in Relay.',
283
- );
284
- switch (entry.status) {
285
- case 'pending':
286
- throw entry.promise;
287
- case 'rejected':
288
- throw entry.error;
289
- case 'resolved':
290
- return [entry.result, entry.onCommit];
291
- }
292
- invariant(false, 'switch statement should be exhaustive');
293
- }
294
-
295
- function onCacheMiss(
296
- environment: IEnvironment,
297
- operation: OperationDescriptor,
298
- fetchPolicy: FetchPolicy,
299
- renderPolicy: RenderPolicy,
300
- updateCache: ((QueryCacheEntryStatus) => QueryCacheEntryStatus) => void,
301
- customFetchObservable?: Observable<GraphQLResponse>,
302
- ): void {
303
- // NB: Besides checking if the data is available, calling `check` will write missing
304
- // data to the store using any missing data handlers specified in the environment.
305
- const queryAvailability = environment.check(operation);
306
- const queryStatus = queryAvailability.status;
307
- const hasFullQuery = queryStatus === 'available';
308
- const canPartialRender =
309
- hasFullQuery || (renderPolicy === 'partial' && queryStatus !== 'stale');
310
-
311
- let shouldFetch;
312
- let shouldRenderNow;
313
- switch (fetchPolicy) {
314
- case 'store-only': {
315
- shouldFetch = false;
316
- shouldRenderNow = true;
317
- break;
318
- }
319
- case 'store-or-network': {
320
- shouldFetch = !hasFullQuery;
321
- shouldRenderNow = canPartialRender;
322
- break;
323
- }
324
- case 'store-and-network': {
325
- shouldFetch = true;
326
- shouldRenderNow = canPartialRender;
327
- break;
328
- }
329
- case 'network-only':
330
- default: {
331
- shouldFetch = true;
332
- shouldRenderNow = false;
333
- break;
334
- }
335
- }
336
-
337
- if (shouldFetch) {
338
- executeOperationAndKeepUpToDate(
339
- environment,
340
- operation,
341
- updateCache,
342
- customFetchObservable,
343
- );
344
- updateCache(existing => {
345
- switch (existing.status) {
346
- case 'resolved':
347
- return existing;
348
- case 'rejected':
349
- return existing;
350
- case 'pending':
351
- return shouldRenderNow
352
- ? {
353
- status: 'resolved',
354
- result: constructQueryResult(operation),
355
- }
356
- : existing;
357
- }
358
- });
359
- } else {
360
- invariant(
361
- shouldRenderNow,
362
- 'Should either fetch or be willing to render. This is a bug in Relay.',
363
- );
364
- updateCache(_existing => ({
365
- status: 'resolved',
366
- result: constructQueryResult(operation),
367
- }));
368
- }
369
- }
370
-
371
- function executeOperationAndKeepUpToDate(
372
- environment: IEnvironment,
373
- operation: OperationDescriptor,
374
- updateCache: ((QueryCacheEntryStatus) => QueryCacheEntryStatus) => void,
375
- customFetchObservable?: Observable<GraphQLResponse>,
376
- ) {
377
- let resolvePromise;
378
- const promise = new Promise<void>(r => {
379
- resolvePromise = r;
380
- });
381
- // $FlowExpectedError[prop-missing] Expando to annotate Promises.
382
- promise.displayName = 'Relay(' + operation.request.node.operation.name + ')';
383
-
384
- let isFirstPayload = true;
385
-
386
- // FIXME We may still need to cancel network requests for live queries.
387
- const fetchObservable =
388
- customFetchObservable ?? fetchQueryInternal(environment, operation);
389
- fetchObservable.subscribe({
390
- start: subscription => {},
391
- error: error => {
392
- if (isFirstPayload) {
393
- updateCache(_existing => ({
394
- status: 'rejected',
395
- error,
396
- }));
397
- } else {
398
- // TODO:T92030819 Remove this warning and actually throw the network error
399
- // To complete this task we need to have a way of precisely tracking suspendable points
400
- warning(
401
- false,
402
- 'getQueryResultOrFetchQuery: An incremental payload for query `%` returned an error: `%`:`%`.',
403
- operation.request.node.operation.name,
404
- error.message,
405
- error.stack,
406
- );
407
- }
408
- resolvePromise();
409
- isFirstPayload = false;
410
- },
411
- next: response => {
412
- // Stop suspending on the first payload because of streaming, defer, etc.
413
- updateCache(_existing => ({
414
- status: 'resolved',
415
- result: constructQueryResult(operation),
416
- }));
417
- resolvePromise();
418
- isFirstPayload = false;
419
- },
420
- });
421
-
422
- // If the above subscription yields a value synchronously, then one of the updates
423
- // above will have already happened and we'll now be in a resolved or rejected state.
424
- // But in the usual case, we save the promise to the entry here:
425
- updateCache(existing =>
426
- existing.status === 'pending' ? {status: 'pending', promise} : existing,
427
- );
428
- }
429
-
430
- module.exports = getQueryResultOrFetchQuery_REACT_CACHE;
@@ -1,70 +0,0 @@
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
- * @flow strict-local
8
- * @format
9
- * @oncall relay
10
- */
11
-
12
- 'use strict';
13
-
14
- import type {
15
- CacheConfig,
16
- FetchPolicy,
17
- Query,
18
- RenderPolicy,
19
- Variables,
20
- } from 'relay-runtime';
21
-
22
- const {useTrackLoadQueryInRender} = require('../loadQuery');
23
- const useMemoOperationDescriptor = require('../useMemoOperationDescriptor');
24
- const useRelayEnvironment = require('../useRelayEnvironment');
25
- const getQueryResultOrFetchQuery = require('./getQueryResultOrFetchQuery_REACT_CACHE');
26
- const useFragmentInternal = require('./useFragmentInternal_REACT_CACHE');
27
- const {useEffect} = require('react');
28
-
29
- function useLazyLoadQuery_REACT_CACHE<TVariables: Variables, TData>(
30
- gqlQuery: Query<TVariables, TData>,
31
- variables: TVariables,
32
- options?: {
33
- fetchKey?: string | number,
34
- fetchPolicy?: FetchPolicy,
35
- networkCacheConfig?: CacheConfig,
36
- UNSTABLE_renderPolicy?: RenderPolicy,
37
- },
38
- ): TData {
39
- useTrackLoadQueryInRender();
40
- const environment = useRelayEnvironment();
41
-
42
- const queryOperationDescriptor = useMemoOperationDescriptor(
43
- gqlQuery,
44
- variables,
45
- options?.networkCacheConfig ?? {force: true},
46
- );
47
-
48
- // Get the query going if needed -- this may suspend.
49
- const [queryResult, effect] = getQueryResultOrFetchQuery(
50
- environment,
51
- queryOperationDescriptor,
52
- {
53
- fetchPolicy: options?.fetchPolicy,
54
- renderPolicy: options?.UNSTABLE_renderPolicy,
55
- fetchKey: options?.fetchKey,
56
- },
57
- );
58
-
59
- useEffect(effect);
60
-
61
- // Read the query's root fragment -- this may suspend.
62
- const {fragmentNode, fragmentRef} = queryResult;
63
- // $FlowExpectedError[incompatible-return] Is this a fixable incompatible-return?
64
- return useFragmentInternal(fragmentNode, fragmentRef, 'useLazyLoadQuery()', {
65
- fetchPolicy: options?.fetchPolicy,
66
- networkCacheConfig: options?.networkCacheConfig,
67
- });
68
- }
69
-
70
- module.exports = useLazyLoadQuery_REACT_CACHE;
@@ -1,150 +0,0 @@
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
- * @flow strict-local
8
- * @format
9
- * @oncall relay
10
- */
11
-
12
- 'use strict';
13
-
14
- import type {PreloadedQuery} from '../EntryPointTypes.flow';
15
- import type {
16
- GraphQLTaggedNode,
17
- OperationType,
18
- RenderPolicy,
19
- } from 'relay-runtime';
20
-
21
- const {useTrackLoadQueryInRender} = require('../loadQuery');
22
- const useMemoOperationDescriptor = require('../useMemoOperationDescriptor');
23
- const useRelayEnvironment = require('../useRelayEnvironment');
24
- const getQueryResultOrFetchQuery = require('./getQueryResultOrFetchQuery_REACT_CACHE');
25
- const useFragmentInternal = require('./useFragmentInternal_REACT_CACHE');
26
- const invariant = require('invariant');
27
- const {useDebugValue, useEffect} = require('react');
28
- const {
29
- __internal: {fetchQueryDeduped, fetchQuery},
30
- } = require('relay-runtime');
31
- const warning = require('warning');
32
-
33
- function usePreloadedQuery_REACT_CACHE<TQuery: OperationType>(
34
- gqlQuery: GraphQLTaggedNode,
35
- preloadedQuery: PreloadedQuery<TQuery>,
36
- options?: {
37
- UNSTABLE_renderPolicy?: RenderPolicy,
38
- },
39
- ): TQuery['response'] {
40
- const environment = useRelayEnvironment();
41
-
42
- useTrackLoadQueryInRender();
43
-
44
- const {fetchKey, fetchPolicy, source, variables, networkCacheConfig} =
45
- preloadedQuery;
46
- const operation = useMemoOperationDescriptor(
47
- gqlQuery,
48
- variables,
49
- networkCacheConfig,
50
- );
51
-
52
- let fetchObservable;
53
- if (preloadedQuery.kind === 'PreloadedQuery_DEPRECATED') {
54
- invariant(
55
- operation.request.node.params.name === preloadedQuery.name,
56
- 'usePreloadedQuery(): Expected data to be prefetched for query `%s`, ' +
57
- 'got prefetch results for query `%s`.',
58
- operation.request.node.params.name,
59
- preloadedQuery.name,
60
- );
61
- fetchObservable = fetchQueryDeduped(
62
- environment,
63
- operation.request.identifier,
64
- () => {
65
- if (environment === preloadedQuery.environment && source != null) {
66
- return environment.executeWithSource({operation, source});
67
- } else {
68
- return environment.execute({operation});
69
- }
70
- },
71
- );
72
- } else {
73
- warning(
74
- preloadedQuery.isDisposed === false,
75
- 'usePreloadedQuery(): Expected preloadedQuery to not be disposed yet. ' +
76
- 'This is because disposing the query marks it for future garbage ' +
77
- 'collection, and as such query results may no longer be present in the Relay ' +
78
- 'store. In the future, this will become a hard error.',
79
- );
80
- const fallbackFetchObservable = fetchQuery(environment, operation);
81
- if (source != null && environment === preloadedQuery.environment) {
82
- // If the source observable exists and the environments match, reuse
83
- // the source observable.
84
- // If the source observable happens to be empty, we need to fall back
85
- // and re-execute and de-dupe the query (at render time).
86
- fetchObservable = source.ifEmpty(fallbackFetchObservable);
87
- } else if (environment !== preloadedQuery.environment) {
88
- // If a call to loadQuery is made with a particular environment, and that
89
- // preloaded query is passed to usePreloadedQuery in a different environment
90
- // context, we cannot re-use the existing preloaded query.
91
- // Instead, we need to fall back and re-execute and de-dupe the query with
92
- // the new environment (at render time).
93
- // TODO T68036756 track occurences of this warning and turn it into a hard error
94
- warning(
95
- false,
96
- 'usePreloadedQuery(): usePreloadedQuery was passed a preloaded query ' +
97
- 'that was created with a different environment than the one that is currently ' +
98
- 'in context. In the future, this will become a hard error.',
99
- );
100
- fetchObservable = fallbackFetchObservable;
101
- } else {
102
- // if (source == null)
103
- // If the source observable does not exist, we need to
104
- // fall back and re-execute and de-dupe the query (at render time).
105
- fetchObservable = fallbackFetchObservable;
106
- }
107
- }
108
-
109
- // Get the query going if needed -- this may suspend.
110
- const [queryResult, effect] = getQueryResultOrFetchQuery(
111
- environment,
112
- operation,
113
- {
114
- fetchPolicy,
115
- renderPolicy: options?.UNSTABLE_renderPolicy,
116
- fetchKey,
117
- fetchObservable,
118
- },
119
- );
120
-
121
- useEffect(effect);
122
-
123
- // Read the query's root fragment -- this may suspend.
124
- const {fragmentNode, fragmentRef} = queryResult;
125
- const data = useFragmentInternal(
126
- fragmentNode,
127
- fragmentRef,
128
- 'usePreloadedQuery()',
129
- {
130
- fetchPolicy: fetchPolicy,
131
- networkCacheConfig: networkCacheConfig,
132
- },
133
- );
134
-
135
- if (__DEV__) {
136
- // eslint-disable-next-line react-hooks/rules-of-hooks
137
- useDebugValue({
138
- query: preloadedQuery.name,
139
- variables: preloadedQuery.variables,
140
- data,
141
- fetchKey,
142
- fetchPolicy,
143
- renderPolicy: options?.UNSTABLE_renderPolicy,
144
- });
145
- }
146
-
147
- return data;
148
- }
149
-
150
- module.exports = usePreloadedQuery_REACT_CACHE;