react-relay 13.1.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/ReactRelayLocalQueryRenderer.js.flow +1 -1
- package/ReactRelayPaginationContainer.js.flow +13 -8
- package/ReactRelayQueryFetcher.js.flow +1 -0
- package/ReactRelayQueryRenderer.js.flow +7 -6
- 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/jest-react/internalAct.js.flow +25 -9
- package/legacy.js +1 -1
- package/lib/ReactRelayQueryFetcher.js +1 -0
- package/lib/ReactRelayQueryRenderer.js +1 -2
- package/lib/jest-react/internalAct.js +24 -4
- package/lib/readContext.js +2 -1
- package/lib/relay-hooks/FragmentResource.js +62 -23
- package/lib/relay-hooks/HooksImplementation.js +29 -0
- package/lib/relay-hooks/MatchContainer.js +1 -0
- package/lib/relay-hooks/QueryResource.js +4 -166
- package/lib/relay-hooks/preloadQuery_DEPRECATED.js +7 -11
- package/lib/relay-hooks/react-cache/RelayReactCache.js +37 -0
- package/lib/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js +344 -0
- package/lib/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js +540 -0
- package/lib/relay-hooks/react-cache/useFragment_REACT_CACHE.js +51 -0
- package/lib/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js +56 -0
- 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 +3 -3
- 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 +72 -27
- package/relay-hooks/HooksImplementation.js.flow +45 -0
- package/relay-hooks/MatchContainer.js.flow +8 -1
- package/relay-hooks/QueryResource.js.flow +8 -203
- 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/preloadQuery_DEPRECATED.js.flow +7 -14
- package/relay-hooks/react-cache/RelayReactCache.js.flow +42 -0
- package/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js.flow +424 -0
- package/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js.flow +559 -0
- package/relay-hooks/react-cache/useFragment_REACT_CACHE.js.flow +74 -0
- package/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js.flow +72 -0
- 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
@@ -32,7 +32,7 @@ import type {
|
|
32
32
|
const LRUCache = require('./LRUCache');
|
33
33
|
const SuspenseResource = require('./SuspenseResource');
|
34
34
|
const invariant = require('invariant');
|
35
|
-
const {
|
35
|
+
const {isPromise} = require('relay-runtime');
|
36
36
|
const warning = require('warning');
|
37
37
|
|
38
38
|
const CACHE_CAPACITY = 1000;
|
@@ -50,8 +50,6 @@ type QueryResourceCacheEntry = {|
|
|
50
50
|
// from the incremental responses, so later we can choose how to handle errors
|
51
51
|
// in the incremental payloads.
|
52
52
|
processedPayloadsCount: number,
|
53
|
-
getRetainCount(): number,
|
54
|
-
getNetworkSubscription(): ?Subscription,
|
55
53
|
setNetworkSubscription(?Subscription): void,
|
56
54
|
getValue(): Error | Promise<void> | QueryResult,
|
57
55
|
setValue(Error | Promise<void> | QueryResult): void,
|
@@ -125,39 +123,6 @@ function createCacheEntry(
|
|
125
123
|
value: Error | Promise<void> | QueryResult,
|
126
124
|
networkSubscription: ?Subscription,
|
127
125
|
onDispose: QueryResourceCacheEntry => void,
|
128
|
-
): QueryResourceCacheEntry {
|
129
|
-
// There should be no behavior difference between createCacheEntry_new and
|
130
|
-
// createCacheEntry_old, and it doesn't directly relate to Client Edges.
|
131
|
-
// It was just a refactoring that was needed for Client Edges but that
|
132
|
-
// is behind the feature flag just in case there is any accidental breakage.
|
133
|
-
if (RelayFeatureFlags.REFACTOR_SUSPENSE_RESOURCE) {
|
134
|
-
return createCacheEntry_new(
|
135
|
-
cacheIdentifier,
|
136
|
-
operation,
|
137
|
-
operationAvailability,
|
138
|
-
value,
|
139
|
-
networkSubscription,
|
140
|
-
onDispose,
|
141
|
-
);
|
142
|
-
} else {
|
143
|
-
return createCacheEntry_old(
|
144
|
-
cacheIdentifier,
|
145
|
-
operation,
|
146
|
-
operationAvailability,
|
147
|
-
value,
|
148
|
-
networkSubscription,
|
149
|
-
onDispose,
|
150
|
-
);
|
151
|
-
}
|
152
|
-
}
|
153
|
-
|
154
|
-
function createCacheEntry_new(
|
155
|
-
cacheIdentifier: string,
|
156
|
-
operation: OperationDescriptor,
|
157
|
-
operationAvailability: ?OperationAvailability,
|
158
|
-
value: Error | Promise<void> | QueryResult,
|
159
|
-
networkSubscription: ?Subscription,
|
160
|
-
onDispose: QueryResourceCacheEntry => void,
|
161
126
|
): QueryResourceCacheEntry {
|
162
127
|
const isLiveQuery = operationIsLiveQuery(operation);
|
163
128
|
|
@@ -191,12 +156,6 @@ function createCacheEntry_new(
|
|
191
156
|
setValue(val: QueryResult | Promise<void> | Error) {
|
192
157
|
currentValue = val;
|
193
158
|
},
|
194
|
-
getRetainCount() {
|
195
|
-
return suspenseResource.getRetainCount();
|
196
|
-
},
|
197
|
-
getNetworkSubscription() {
|
198
|
-
return currentNetworkSubscription;
|
199
|
-
},
|
200
159
|
setNetworkSubscription(subscription: ?Subscription) {
|
201
160
|
if (isLiveQuery && currentNetworkSubscription != null) {
|
202
161
|
currentNetworkSubscription.unsubscribe();
|
@@ -217,153 +176,6 @@ function createCacheEntry_new(
|
|
217
176
|
return cacheEntry;
|
218
177
|
}
|
219
178
|
|
220
|
-
const DATA_RETENTION_TIMEOUT = 5 * 60 * 1000;
|
221
|
-
function createCacheEntry_old(
|
222
|
-
cacheIdentifier: string,
|
223
|
-
operation: OperationDescriptor,
|
224
|
-
operationAvailability: ?OperationAvailability,
|
225
|
-
value: Error | Promise<void> | QueryResult,
|
226
|
-
networkSubscription: ?Subscription,
|
227
|
-
onDispose: QueryResourceCacheEntry => void,
|
228
|
-
): QueryResourceCacheEntry {
|
229
|
-
const isLiveQuery = operationIsLiveQuery(operation);
|
230
|
-
|
231
|
-
let currentValue: Error | Promise<void> | QueryResult = value;
|
232
|
-
let retainCount = 0;
|
233
|
-
let retainDisposable: ?Disposable = null;
|
234
|
-
let releaseTemporaryRetain: ?() => void = null;
|
235
|
-
let currentNetworkSubscription: ?Subscription = networkSubscription;
|
236
|
-
|
237
|
-
const retain = (environment: IEnvironment) => {
|
238
|
-
retainCount++;
|
239
|
-
if (retainCount === 1) {
|
240
|
-
retainDisposable = environment.retain(operation);
|
241
|
-
}
|
242
|
-
return {
|
243
|
-
dispose: () => {
|
244
|
-
retainCount = Math.max(0, retainCount - 1);
|
245
|
-
if (retainCount === 0) {
|
246
|
-
invariant(
|
247
|
-
retainDisposable != null,
|
248
|
-
'Relay: Expected disposable to release query to be defined.' +
|
249
|
-
"If you're seeing this, this is likely a bug in Relay.",
|
250
|
-
);
|
251
|
-
retainDisposable.dispose();
|
252
|
-
retainDisposable = null;
|
253
|
-
}
|
254
|
-
onDispose(cacheEntry);
|
255
|
-
},
|
256
|
-
};
|
257
|
-
};
|
258
|
-
|
259
|
-
const cacheEntry = {
|
260
|
-
cacheIdentifier,
|
261
|
-
id: nextID++,
|
262
|
-
processedPayloadsCount: 0,
|
263
|
-
operationAvailability,
|
264
|
-
getValue() {
|
265
|
-
return currentValue;
|
266
|
-
},
|
267
|
-
setValue(val: QueryResult | Promise<void> | Error) {
|
268
|
-
currentValue = val;
|
269
|
-
},
|
270
|
-
getRetainCount() {
|
271
|
-
return retainCount;
|
272
|
-
},
|
273
|
-
getNetworkSubscription() {
|
274
|
-
return currentNetworkSubscription;
|
275
|
-
},
|
276
|
-
setNetworkSubscription(subscription: ?Subscription) {
|
277
|
-
if (isLiveQuery && currentNetworkSubscription != null) {
|
278
|
-
currentNetworkSubscription.unsubscribe();
|
279
|
-
}
|
280
|
-
currentNetworkSubscription = subscription;
|
281
|
-
},
|
282
|
-
temporaryRetain(environment: IEnvironment): Disposable {
|
283
|
-
// NOTE: If we're executing in a server environment, there's no need
|
284
|
-
// to create temporary retains, since the component will never commit.
|
285
|
-
if (environment.isServer()) {
|
286
|
-
return {dispose: () => {}};
|
287
|
-
}
|
288
|
-
|
289
|
-
// NOTE: temporaryRetain is called during the render phase. However,
|
290
|
-
// given that we can't tell if this render will eventually commit or not,
|
291
|
-
// we create a timer to autodispose of this retain in case the associated
|
292
|
-
// component never commits.
|
293
|
-
// If the component /does/ commit, permanentRetain will clear this timeout
|
294
|
-
// and permanently retain the data.
|
295
|
-
const disposable = retain(environment);
|
296
|
-
let releaseQueryTimeout = null;
|
297
|
-
const localReleaseTemporaryRetain = () => {
|
298
|
-
clearTimeout(releaseQueryTimeout);
|
299
|
-
releaseQueryTimeout = null;
|
300
|
-
releaseTemporaryRetain = null;
|
301
|
-
disposable.dispose();
|
302
|
-
// Normally if this entry never commits, the request would've ended by the
|
303
|
-
// time this timeout expires and the temporary retain is released. However,
|
304
|
-
// we need to do this for live queries which remain open indefinitely.
|
305
|
-
if (
|
306
|
-
isLiveQuery &&
|
307
|
-
retainCount <= 0 &&
|
308
|
-
currentNetworkSubscription != null
|
309
|
-
) {
|
310
|
-
currentNetworkSubscription.unsubscribe();
|
311
|
-
}
|
312
|
-
};
|
313
|
-
releaseQueryTimeout = setTimeout(
|
314
|
-
localReleaseTemporaryRetain,
|
315
|
-
DATA_RETENTION_TIMEOUT,
|
316
|
-
);
|
317
|
-
|
318
|
-
// NOTE: Since temporaryRetain can be called multiple times, we release
|
319
|
-
// the previous temporary retain after we re-establish a new one, since
|
320
|
-
// we only ever need a single temporary retain until the permanent retain is
|
321
|
-
// established.
|
322
|
-
// temporaryRetain may be called multiple times by React during the render
|
323
|
-
// phase, as well as multiple times by other query components that are
|
324
|
-
// rendering the same query/variables.
|
325
|
-
if (releaseTemporaryRetain != null) {
|
326
|
-
releaseTemporaryRetain();
|
327
|
-
}
|
328
|
-
releaseTemporaryRetain = localReleaseTemporaryRetain;
|
329
|
-
|
330
|
-
return {
|
331
|
-
dispose: () => {
|
332
|
-
releaseTemporaryRetain && releaseTemporaryRetain();
|
333
|
-
},
|
334
|
-
};
|
335
|
-
},
|
336
|
-
permanentRetain(environment: IEnvironment): Disposable {
|
337
|
-
const disposable = retain(environment);
|
338
|
-
if (releaseTemporaryRetain != null) {
|
339
|
-
releaseTemporaryRetain();
|
340
|
-
releaseTemporaryRetain = null;
|
341
|
-
}
|
342
|
-
|
343
|
-
return {
|
344
|
-
dispose: () => {
|
345
|
-
disposable.dispose();
|
346
|
-
if (
|
347
|
-
isLiveQuery &&
|
348
|
-
retainCount <= 0 &&
|
349
|
-
currentNetworkSubscription != null
|
350
|
-
) {
|
351
|
-
currentNetworkSubscription.unsubscribe();
|
352
|
-
}
|
353
|
-
},
|
354
|
-
};
|
355
|
-
},
|
356
|
-
releaseTemporaryRetain() {
|
357
|
-
if (releaseTemporaryRetain != null) {
|
358
|
-
releaseTemporaryRetain();
|
359
|
-
releaseTemporaryRetain = null;
|
360
|
-
}
|
361
|
-
},
|
362
|
-
};
|
363
|
-
|
364
|
-
return cacheEntry;
|
365
|
-
}
|
366
|
-
|
367
179
|
class QueryResourceImpl {
|
368
180
|
_environment: IEnvironment;
|
369
181
|
_cache: QueryResourceCache;
|
@@ -532,15 +344,7 @@ class QueryResourceImpl {
|
|
532
344
|
}
|
533
345
|
|
534
346
|
_clearCacheEntry = (cacheEntry: QueryResourceCacheEntry): void => {
|
535
|
-
|
536
|
-
// before calling _clearCacheEntry, whereas with the old code we do it here.
|
537
|
-
if (RelayFeatureFlags.REFACTOR_SUSPENSE_RESOURCE) {
|
538
|
-
this._cache.delete(cacheEntry.cacheIdentifier);
|
539
|
-
} else {
|
540
|
-
if (cacheEntry.getRetainCount() <= 0) {
|
541
|
-
this._cache.delete(cacheEntry.cacheIdentifier);
|
542
|
-
}
|
543
|
-
}
|
347
|
+
this._cache.delete(cacheEntry.cacheIdentifier);
|
544
348
|
};
|
545
349
|
|
546
350
|
_getOrCreateCacheEntry(
|
@@ -588,7 +392,9 @@ class QueryResourceImpl {
|
|
588
392
|
|
589
393
|
let shouldFetch;
|
590
394
|
let shouldAllowRender;
|
591
|
-
|
395
|
+
// Different definitions for Promise in our repos can cause this variable
|
396
|
+
// to cause errors when synced elsewhere
|
397
|
+
let resolveNetworkPromise: $FlowFixMe = () => {};
|
592
398
|
switch (fetchPolicy) {
|
593
399
|
case 'store-only': {
|
594
400
|
shouldFetch = false;
|
@@ -632,7 +438,7 @@ class QueryResourceImpl {
|
|
632
438
|
|
633
439
|
if (shouldFetch) {
|
634
440
|
const queryResult = getQueryResult(operation, cacheIdentifier);
|
635
|
-
let networkSubscription;
|
441
|
+
let networkSubscription: ?Subscription;
|
636
442
|
fetchObservable.subscribe({
|
637
443
|
start: subscription => {
|
638
444
|
networkSubscription = subscription;
|
@@ -693,10 +499,9 @@ class QueryResourceImpl {
|
|
693
499
|
// To complete this task we need to have a way of precisely tracking suspendable points
|
694
500
|
warning(
|
695
501
|
false,
|
696
|
-
'QueryResource: An incremental payload for query
|
502
|
+
'QueryResource: An incremental payload for query `%s` returned an error: `%s`.',
|
697
503
|
operation.fragment.node.name,
|
698
|
-
error.message,
|
699
|
-
error.stack,
|
504
|
+
String(error.message),
|
700
505
|
);
|
701
506
|
}
|
702
507
|
resolveNetworkPromise();
|
@@ -1,10 +1,10 @@
|
|
1
1
|
/**
|
2
2
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
3
|
-
*
|
3
|
+
*
|
4
4
|
* This source code is licensed under the MIT license found in the
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
6
6
|
*
|
7
|
-
* @generated SignedSource<<
|
7
|
+
* @generated SignedSource<<8a8e68a3fde4da3f77546ac4952f2635>>
|
8
8
|
* @flow
|
9
9
|
* @lightSyntaxTransform
|
10
10
|
* @nogrep
|
@@ -1,10 +1,10 @@
|
|
1
1
|
/**
|
2
2
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
3
|
-
*
|
3
|
+
*
|
4
4
|
* This source code is licensed under the MIT license found in the
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
6
6
|
*
|
7
|
-
* @generated SignedSource<<
|
7
|
+
* @generated SignedSource<<0b4a6e76a104111de9ddd4dd9abe667c>>
|
8
8
|
* @flow
|
9
9
|
* @lightSyntaxTransform
|
10
10
|
* @nogrep
|
@@ -17,6 +17,7 @@ import type {
|
|
17
17
|
PreloadedQueryInner,
|
18
18
|
} from './EntryPointTypes.flow';
|
19
19
|
import type {
|
20
|
+
ConcreteRequest,
|
20
21
|
GraphQLResponse,
|
21
22
|
GraphQLTaggedNode,
|
22
23
|
IEnvironment,
|
@@ -236,7 +237,7 @@ function loadQuery<TQuery: OperationType, TEnvironmentProviderOptions>(
|
|
236
237
|
}));
|
237
238
|
};
|
238
239
|
|
239
|
-
const checkAvailabilityAndExecute = concreteRequest => {
|
240
|
+
const checkAvailabilityAndExecute = (concreteRequest: ConcreteRequest) => {
|
240
241
|
const operation = createOperationDescriptor(
|
241
242
|
concreteRequest,
|
242
243
|
variables,
|
@@ -115,20 +115,13 @@ function preloadQuery<TQuery: OperationType, TEnvironmentProviderOptions>(
|
|
115
115
|
if (environment.isServer()) {
|
116
116
|
return;
|
117
117
|
}
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
if (queryEntry != null) {
|
126
|
-
cleanup(pendingQueries, queryEntry);
|
127
|
-
}
|
128
|
-
}, DEFAULT_PREFETCH_TIMEOUT);
|
129
|
-
} else {
|
130
|
-
cleanup(pendingQueries, queryEntry);
|
131
|
-
}
|
118
|
+
setTimeout(() => {
|
119
|
+
// Clear the cache entry after the default timeout
|
120
|
+
// null-check for Flow
|
121
|
+
if (queryEntry != null) {
|
122
|
+
cleanup(pendingQueries, queryEntry);
|
123
|
+
}
|
124
|
+
}, DEFAULT_PREFETCH_TIMEOUT);
|
132
125
|
};
|
133
126
|
})
|
134
127
|
: null;
|
@@ -0,0 +1,42 @@
|
|
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
|
+
* @emails oncall+relay
|
9
|
+
* @format
|
10
|
+
*/
|
11
|
+
|
12
|
+
// flowlint ambiguous-object-type:error
|
13
|
+
|
14
|
+
'use strict';
|
15
|
+
|
16
|
+
const invariant = require('invariant');
|
17
|
+
// $FlowFixMe[prop-missing] These exist in experimental builds but aren't in React's types yet.
|
18
|
+
const {unstable_getCacheForType, unstable_getCacheSignal} = require('react');
|
19
|
+
const {RelayFeatureFlags} = require('relay-runtime');
|
20
|
+
|
21
|
+
function getCacheForType<T>(factory: () => T): T {
|
22
|
+
invariant(
|
23
|
+
typeof unstable_getCacheForType === 'function' &&
|
24
|
+
RelayFeatureFlags.USE_REACT_CACHE,
|
25
|
+
'RelayReactCache.getCacheForType should only be called when the USE_REACT_CACHE feature flag is enabled and when on an experimental React build that supports it.',
|
26
|
+
);
|
27
|
+
return unstable_getCacheForType(factory);
|
28
|
+
}
|
29
|
+
|
30
|
+
function getCacheSignal(): AbortSignal {
|
31
|
+
invariant(
|
32
|
+
typeof unstable_getCacheSignal === 'function' &&
|
33
|
+
RelayFeatureFlags.USE_REACT_CACHE,
|
34
|
+
'RelayReactCache.getCacheSignal should only be called when the USE_REACT_CACHE feature flag is enabled and when on an experimental React build that supports it.',
|
35
|
+
);
|
36
|
+
return unstable_getCacheSignal();
|
37
|
+
}
|
38
|
+
|
39
|
+
module.exports = {
|
40
|
+
getCacheForType,
|
41
|
+
getCacheSignal,
|
42
|
+
};
|