react-relay 16.0.0 → 16.2.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/ReactRelayTypes.js.flow +1 -0
- package/hooks.js +1 -1
- package/hooks.js.flow +1 -1
- package/index.js +1 -1
- package/index.js.flow +1 -1
- package/legacy.js +1 -1
- package/lib/relay-hooks/HooksImplementation.js +1 -1
- package/lib/relay-hooks/SuspenseResource.js +7 -4
- package/lib/relay-hooks/{react-cache/readFragmentInternal_REACT_CACHE.js → experimental/readFragmentInternal_EXPERIMENTAL.js} +4 -4
- package/lib/relay-hooks/{react-cache/useFragmentInternal_REACT_CACHE.js → experimental/useFragmentInternal_EXPERIMENTAL.js} +63 -29
- package/lib/relay-hooks/{react-cache/useFragment_REACT_CACHE.js → experimental/useFragment_EXPERIMENTAL.js} +1 -1
- package/lib/relay-hooks/{react-cache/usePaginationFragment_REACT_CACHE.js → experimental/usePaginationFragment_EXPERIMENTAL.js} +1 -1
- package/lib/relay-hooks/{react-cache/useRefetchableFragmentInternal_REACT_CACHE.js → experimental/useRefetchableFragmentInternal_EXPERIMENTAL.js} +2 -2
- package/lib/relay-hooks/{react-cache/useRefetchableFragment_REACT_CACHE.js → experimental/useRefetchableFragment_EXPERIMENTAL.js} +1 -1
- package/lib/relay-hooks/{FragmentResource.js → legacy/FragmentResource.js} +7 -6
- package/lib/relay-hooks/{useBlockingPaginationFragment.js → legacy/useBlockingPaginationFragment.js} +2 -2
- package/lib/relay-hooks/{useFragmentNode.js → legacy/useFragmentNode.js} +2 -2
- package/lib/relay-hooks/{useRefetchableFragmentNode.js → legacy/useRefetchableFragmentNode.js} +8 -8
- package/lib/relay-hooks/useFragment.js +1 -1
- package/lib/relay-hooks/useLazyLoadQueryNode.js +13 -3
- package/lib/relay-hooks/usePaginationFragment.js +1 -1
- package/lib/relay-hooks/useRefetchableFragment.js +1 -1
- 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/relay-hooks/EntryPointTypes.flow.js.flow +25 -33
- package/relay-hooks/HooksImplementation.js.flow +3 -1
- package/relay-hooks/NestedRelayEntryPointBuilderUtils.js.flow +5 -11
- package/relay-hooks/SuspenseResource.js.flow +11 -8
- package/relay-hooks/__flowtests__/useBlockingPaginationFragment-flowtest.js.flow +1 -1
- package/relay-hooks/{react-cache/readFragmentInternal_REACT_CACHE.js.flow → experimental/readFragmentInternal_EXPERIMENTAL.js.flow} +4 -2
- package/relay-hooks/{react-cache/useFragmentInternal_REACT_CACHE.js.flow → experimental/useFragmentInternal_EXPERIMENTAL.js.flow} +61 -18
- package/relay-hooks/{react-cache/useFragment_REACT_CACHE.js.flow → experimental/useFragment_EXPERIMENTAL.js.flow} +10 -4
- package/relay-hooks/{react-cache/usePaginationFragment_REACT_CACHE.js.flow → experimental/usePaginationFragment_EXPERIMENTAL.js.flow} +2 -2
- package/relay-hooks/{react-cache/useRefetchableFragmentInternal_REACT_CACHE.js.flow → experimental/useRefetchableFragmentInternal_EXPERIMENTAL.js.flow} +11 -11
- package/relay-hooks/{react-cache/useRefetchableFragment_REACT_CACHE.js.flow → experimental/useRefetchableFragment_EXPERIMENTAL.js.flow} +1 -1
- package/relay-hooks/{FragmentResource.js.flow → legacy/FragmentResource.js.flow} +8 -5
- package/relay-hooks/{useBlockingPaginationFragment.js.flow → legacy/useBlockingPaginationFragment.js.flow} +13 -18
- package/relay-hooks/{useFragmentNode.js.flow → legacy/useFragmentNode.js.flow} +2 -2
- package/relay-hooks/{useRefetchableFragmentNode.js.flow → legacy/useRefetchableFragmentNode.js.flow} +12 -14
- package/relay-hooks/loadQuery.js.flow +1 -1
- package/relay-hooks/useFragment.js.flow +10 -4
- package/relay-hooks/useLazyLoadQueryNode.js.flow +18 -2
- package/relay-hooks/usePaginationFragment.js.flow +7 -9
- package/relay-hooks/useRefetchableFragment.js.flow +15 -18
- package/lib/relay-hooks/react-cache/RelayReactCache.js +0 -20
- package/lib/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js +0 -255
- package/lib/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js +0 -33
- package/lib/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js +0 -81
- package/relay-hooks/react-cache/RelayReactCache.js.flow +0 -40
- package/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js.flow +0 -430
- package/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js.flow +0 -70
- 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;
|