react-relay 12.0.0 → 13.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/LICENSE +1 -1
- package/README.md +47 -0
- package/ReactRelayContainerUtils.js.flow +1 -1
- package/ReactRelayContext.js +2 -2
- package/ReactRelayContext.js.flow +3 -4
- package/ReactRelayFragmentContainer.js.flow +11 -17
- package/ReactRelayFragmentMockRenderer.js.flow +2 -2
- package/ReactRelayLocalQueryRenderer.js.flow +7 -8
- package/ReactRelayPaginationContainer.js.flow +30 -40
- package/ReactRelayQueryFetcher.js.flow +10 -11
- package/ReactRelayQueryRenderer.js.flow +16 -16
- package/ReactRelayQueryRendererContext.js.flow +1 -1
- package/ReactRelayRefetchContainer.js.flow +25 -33
- package/ReactRelayTestMocker.js.flow +17 -15
- package/ReactRelayTypes.js.flow +11 -11
- package/RelayContext.js.flow +4 -4
- package/__flowtests__/ReactRelayFragmentContainer-flowtest.js.flow +2 -3
- package/__flowtests__/ReactRelayPaginationContainer-flowtest.js.flow +2 -3
- package/__flowtests__/ReactRelayRefetchContainer-flowtest.js.flow +2 -3
- package/__flowtests__/RelayModern-flowtest.js.flow +79 -47
- package/__flowtests__/RelayModernFlowtest_badref.graphql.js.flow +6 -5
- package/__flowtests__/RelayModernFlowtest_notref.graphql.js.flow +6 -5
- package/__flowtests__/RelayModernFlowtest_user.graphql.js.flow +5 -4
- package/__flowtests__/RelayModernFlowtest_users.graphql.js.flow +5 -4
- package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer.graphql.js.flow +14 -11
- package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer2.graphql.js.flow +14 -11
- package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtestQuery.graphql.js.flow +14 -9
- package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtest_viewer.graphql.js.flow +14 -11
- package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtestQuery.graphql.js.flow +14 -9
- package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtest_viewer.graphql.js.flow +14 -11
- package/__flowtests__/__generated__/RelayModernFlowtest_badref.graphql.js.flow +16 -13
- package/__flowtests__/__generated__/RelayModernFlowtest_notref.graphql.js.flow +16 -13
- package/__flowtests__/__generated__/RelayModernFlowtest_user.graphql.js.flow +14 -11
- package/__flowtests__/__generated__/RelayModernFlowtest_users.graphql.js.flow +14 -11
- package/assertFragmentMap.js.flow +3 -3
- package/buildReactRelayContainer.js.flow +12 -11
- package/getRootVariablesForFragments.js.flow +3 -5
- package/hooks.js +2 -2
- package/hooks.js.flow +4 -6
- package/index.js +2 -2
- package/index.js.flow +5 -7
- package/isRelayEnvironment.js.flow +1 -1
- package/jest-react/enqueueTask.js.flow +2 -2
- package/jest-react/index.js.flow +1 -1
- package/jest-react/internalAct.js.flow +2 -4
- package/legacy.js +2 -2
- package/legacy.js.flow +1 -1
- package/lib/ReactRelayContainerUtils.js +1 -1
- package/lib/ReactRelayContext.js +1 -1
- package/lib/ReactRelayFragmentContainer.js +5 -5
- package/lib/ReactRelayFragmentMockRenderer.js +3 -3
- package/lib/ReactRelayLocalQueryRenderer.js +8 -9
- package/lib/ReactRelayPaginationContainer.js +19 -23
- package/lib/ReactRelayQueryFetcher.js +3 -3
- package/lib/ReactRelayQueryRenderer.js +5 -5
- package/lib/ReactRelayQueryRendererContext.js +1 -1
- package/lib/ReactRelayRefetchContainer.js +13 -15
- package/lib/ReactRelayTestMocker.js +8 -9
- package/lib/ReactRelayTypes.js +1 -1
- package/lib/RelayContext.js +4 -3
- package/lib/assertFragmentMap.js +3 -2
- package/lib/buildReactRelayContainer.js +8 -8
- package/lib/getRootVariablesForFragments.js +2 -3
- package/lib/hooks.js +6 -6
- package/lib/index.js +8 -8
- package/lib/isRelayEnvironment.js +1 -1
- package/lib/jest-react/enqueueTask.js +1 -1
- package/lib/jest-react/internalAct.js +3 -4
- package/lib/legacy.js +1 -1
- package/lib/multi-actor/ActorChange.js +3 -3
- package/lib/multi-actor/index.js +1 -1
- package/lib/multi-actor/useRelayActorEnvironment.js +3 -3
- package/lib/readContext.js +1 -1
- package/lib/relay-hooks/EntryPointContainer.react.js +4 -4
- package/lib/relay-hooks/EntryPointTypes.flow.js +1 -1
- package/lib/relay-hooks/FragmentResource.js +242 -46
- package/lib/relay-hooks/InternalLogger.js +1 -1
- package/lib/relay-hooks/LRUCache.js +1 -1
- package/lib/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js +5 -5
- package/lib/relay-hooks/MatchContainer.js +2 -2
- package/lib/relay-hooks/ProfilerContext.js +1 -1
- package/lib/relay-hooks/QueryResource.js +84 -5
- package/lib/relay-hooks/RelayEnvironmentProvider.js +1 -1
- package/lib/relay-hooks/SuspenseResource.js +130 -0
- package/lib/relay-hooks/loadEntryPoint.js +1 -1
- package/lib/relay-hooks/loadQuery.js +9 -10
- package/lib/relay-hooks/preloadQuery_DEPRECATED.js +25 -11
- package/lib/relay-hooks/prepareEntryPoint_DEPRECATED.js +1 -1
- package/lib/relay-hooks/useBlockingPaginationFragment.js +3 -3
- package/lib/relay-hooks/useEntryPointLoader.js +3 -3
- package/lib/relay-hooks/useFetchTrackingRef.js +3 -2
- package/lib/relay-hooks/useFragment.js +7 -7
- package/lib/relay-hooks/useFragmentNode.js +5 -5
- package/lib/relay-hooks/useIsMountedRef.js +1 -1
- package/lib/relay-hooks/useIsOperationNodeActive.js +3 -3
- package/lib/relay-hooks/useIsParentQueryActive.js +1 -1
- package/lib/relay-hooks/useLazyLoadQuery.js +4 -4
- package/lib/relay-hooks/useLazyLoadQueryNode.js +5 -5
- package/lib/relay-hooks/useLoadMoreFunction.js +8 -10
- package/lib/relay-hooks/useMemoOperationDescriptor.js +3 -3
- package/lib/relay-hooks/useMemoVariables.js +3 -3
- package/lib/relay-hooks/useMutation.js +18 -7
- package/lib/relay-hooks/usePaginationFragment.js +1 -1
- package/lib/relay-hooks/usePreloadedQuery.js +6 -6
- package/lib/relay-hooks/useQueryLoader.js +5 -5
- package/lib/relay-hooks/useRefetchableFragment.js +1 -1
- package/lib/relay-hooks/useRefetchableFragmentNode.js +11 -13
- package/lib/relay-hooks/useRelayEnvironment.js +3 -3
- package/lib/relay-hooks/useStaticFragmentNodeWarning.js +3 -3
- package/lib/relay-hooks/useSubscribeToInvalidationState.js +3 -2
- package/lib/relay-hooks/useSubscription.js +1 -1
- package/multi-actor/ActorChange.js.flow +4 -5
- package/multi-actor/index.js.flow +1 -1
- package/multi-actor/useRelayActorEnvironment.js.flow +6 -8
- package/package.json +3 -3
- package/react-relay-hooks.js +2 -2
- package/react-relay-hooks.min.js +3 -3
- package/react-relay-legacy.js +2 -2
- package/react-relay-legacy.min.js +3 -3
- package/react-relay.js +2 -2
- package/react-relay.min.js +3 -3
- package/readContext.js.flow +1 -1
- package/relay-hooks/EntryPointContainer.react.js.flow +9 -16
- package/relay-hooks/EntryPointTypes.flow.js.flow +19 -25
- package/relay-hooks/FragmentResource.js.flow +221 -35
- package/relay-hooks/InternalLogger.js.flow +1 -1
- package/relay-hooks/LRUCache.js.flow +1 -1
- package/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js.flow +33 -47
- package/relay-hooks/MatchContainer.js.flow +4 -3
- package/relay-hooks/ProfilerContext.js.flow +1 -1
- package/relay-hooks/QueryResource.js.flow +120 -18
- package/relay-hooks/RelayEnvironmentProvider.js.flow +10 -10
- package/relay-hooks/SuspenseResource.js.flow +115 -0
- package/relay-hooks/__flowtests__/EntryPointTypes/EntryPointElementConfig-flowtest.js.flow +5 -4
- package/relay-hooks/__flowtests__/EntryPointTypes/NestedEntrypoints-flowtest.js.flow +2 -2
- package/relay-hooks/__flowtests__/__generated__/useFragmentFlowtest_user.graphql.js.flow +59 -0
- package/relay-hooks/__flowtests__/__generated__/useFragmentFlowtest_users.graphql.js.flow +61 -0
- package/relay-hooks/__flowtests__/useBlockingPaginationFragment-flowtest.js.flow +11 -10
- package/relay-hooks/__flowtests__/useFragment-flowtest.js.flow +55 -32
- package/relay-hooks/__flowtests__/usePaginationFragment-flowtest.js.flow +11 -10
- package/relay-hooks/__flowtests__/useRefetchableFragment-flowtest.js.flow +11 -10
- package/relay-hooks/__flowtests__/utils.js.flow +21 -32
- package/relay-hooks/loadEntryPoint.js.flow +7 -13
- package/relay-hooks/loadQuery.js.flow +23 -24
- package/relay-hooks/preloadQuery_DEPRECATED.js.flow +30 -14
- package/relay-hooks/prepareEntryPoint_DEPRECATED.js.flow +7 -13
- package/relay-hooks/useBlockingPaginationFragment.js.flow +13 -14
- package/relay-hooks/useEntryPointLoader.js.flow +8 -11
- package/relay-hooks/useFetchTrackingRef.js.flow +3 -3
- package/relay-hooks/useFragment.js.flow +31 -62
- package/relay-hooks/useFragmentNode.js.flow +6 -8
- package/relay-hooks/useIsMountedRef.js.flow +1 -1
- package/relay-hooks/useIsOperationNodeActive.js.flow +4 -6
- package/relay-hooks/useIsParentQueryActive.js.flow +4 -5
- package/relay-hooks/useLazyLoadQuery.js.flow +14 -16
- package/relay-hooks/useLazyLoadQueryNode.js.flow +12 -14
- package/relay-hooks/useLoadMoreFunction.js.flow +20 -28
- package/relay-hooks/useMemoOperationDescriptor.js.flow +6 -8
- package/relay-hooks/useMemoVariables.js.flow +7 -7
- package/relay-hooks/useMutation.js.flow +27 -27
- package/relay-hooks/usePaginationFragment.js.flow +38 -47
- package/relay-hooks/usePreloadedQuery.js.flow +14 -20
- package/relay-hooks/useQueryLoader.js.flow +14 -17
- package/relay-hooks/useRefetchableFragment.js.flow +8 -9
- package/relay-hooks/useRefetchableFragmentNode.js.flow +23 -31
- package/relay-hooks/useRelayEnvironment.js.flow +3 -5
- package/relay-hooks/useStaticFragmentNodeWarning.js.flow +3 -4
- package/relay-hooks/useSubscribeToInvalidationState.js.flow +4 -7
- package/relay-hooks/useSubscription.js.flow +7 -8
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright (c)
|
|
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.
|
|
@@ -13,19 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
'use strict';
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const invariant = require('invariant');
|
|
19
|
-
const warning = require('warning');
|
|
20
|
-
|
|
21
|
-
const {isPromise} = require('relay-runtime');
|
|
22
|
-
|
|
23
|
-
const CACHE_CAPACITY = 1000;
|
|
24
|
-
|
|
25
|
-
const DEFAULT_FETCH_POLICY = 'store-or-network';
|
|
26
|
-
|
|
27
|
-
const DATA_RETENTION_TIMEOUT = 5 * 60 * 1000;
|
|
28
|
-
|
|
16
|
+
import type {Cache} from './LRUCache';
|
|
29
17
|
import type {
|
|
30
18
|
Disposable,
|
|
31
19
|
FetchPolicy,
|
|
@@ -40,7 +28,15 @@ import type {
|
|
|
40
28
|
Snapshot,
|
|
41
29
|
Subscription,
|
|
42
30
|
} from 'relay-runtime';
|
|
43
|
-
|
|
31
|
+
|
|
32
|
+
const LRUCache = require('./LRUCache');
|
|
33
|
+
const SuspenseResource = require('./SuspenseResource');
|
|
34
|
+
const invariant = require('invariant');
|
|
35
|
+
const {RelayFeatureFlags, isPromise} = require('relay-runtime');
|
|
36
|
+
const warning = require('warning');
|
|
37
|
+
|
|
38
|
+
const CACHE_CAPACITY = 1000;
|
|
39
|
+
const DEFAULT_FETCH_POLICY = 'store-or-network';
|
|
44
40
|
|
|
45
41
|
export type QueryResource = QueryResourceImpl;
|
|
46
42
|
|
|
@@ -63,7 +59,7 @@ type QueryResourceCacheEntry = {|
|
|
|
63
59
|
permanentRetain(environment: IEnvironment): Disposable,
|
|
64
60
|
releaseTemporaryRetain(): void,
|
|
65
61
|
|};
|
|
66
|
-
opaque type QueryResult: {
|
|
62
|
+
export opaque type QueryResult: {
|
|
67
63
|
fragmentNode: ReaderFragment,
|
|
68
64
|
fragmentRef: mixed,
|
|
69
65
|
...
|
|
@@ -129,6 +125,106 @@ function createCacheEntry(
|
|
|
129
125
|
value: Error | Promise<void> | QueryResult,
|
|
130
126
|
networkSubscription: ?Subscription,
|
|
131
127
|
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
|
+
): QueryResourceCacheEntry {
|
|
162
|
+
const isLiveQuery = operationIsLiveQuery(operation);
|
|
163
|
+
|
|
164
|
+
let currentValue: Error | Promise<void> | QueryResult = value;
|
|
165
|
+
let currentNetworkSubscription: ?Subscription = networkSubscription;
|
|
166
|
+
|
|
167
|
+
const suspenseResource = new SuspenseResource(environment => {
|
|
168
|
+
const retention = environment.retain(operation);
|
|
169
|
+
return {
|
|
170
|
+
dispose: () => {
|
|
171
|
+
// Normally if this entry never commits, the request would've ended by the
|
|
172
|
+
// time this timeout expires and the temporary retain is released. However,
|
|
173
|
+
// we need to do this for live queries which remain open indefinitely.
|
|
174
|
+
if (isLiveQuery && currentNetworkSubscription != null) {
|
|
175
|
+
currentNetworkSubscription.unsubscribe();
|
|
176
|
+
}
|
|
177
|
+
retention.dispose();
|
|
178
|
+
onDispose(cacheEntry);
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
const cacheEntry = {
|
|
184
|
+
cacheIdentifier,
|
|
185
|
+
id: nextID++,
|
|
186
|
+
processedPayloadsCount: 0,
|
|
187
|
+
operationAvailability,
|
|
188
|
+
getValue() {
|
|
189
|
+
return currentValue;
|
|
190
|
+
},
|
|
191
|
+
setValue(val: QueryResult | Promise<void> | Error) {
|
|
192
|
+
currentValue = val;
|
|
193
|
+
},
|
|
194
|
+
getRetainCount() {
|
|
195
|
+
return suspenseResource.getRetainCount();
|
|
196
|
+
},
|
|
197
|
+
getNetworkSubscription() {
|
|
198
|
+
return currentNetworkSubscription;
|
|
199
|
+
},
|
|
200
|
+
setNetworkSubscription(subscription: ?Subscription) {
|
|
201
|
+
if (isLiveQuery && currentNetworkSubscription != null) {
|
|
202
|
+
currentNetworkSubscription.unsubscribe();
|
|
203
|
+
}
|
|
204
|
+
currentNetworkSubscription = subscription;
|
|
205
|
+
},
|
|
206
|
+
temporaryRetain(environment: IEnvironment): Disposable {
|
|
207
|
+
return suspenseResource.temporaryRetain(environment);
|
|
208
|
+
},
|
|
209
|
+
permanentRetain(environment: IEnvironment): Disposable {
|
|
210
|
+
return suspenseResource.permanentRetain(environment);
|
|
211
|
+
},
|
|
212
|
+
releaseTemporaryRetain() {
|
|
213
|
+
suspenseResource.releaseTemporaryRetain();
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
return cacheEntry;
|
|
218
|
+
}
|
|
219
|
+
|
|
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,
|
|
132
228
|
): QueryResourceCacheEntry {
|
|
133
229
|
const isLiveQuery = operationIsLiveQuery(operation);
|
|
134
230
|
|
|
@@ -168,7 +264,7 @@ function createCacheEntry(
|
|
|
168
264
|
getValue() {
|
|
169
265
|
return currentValue;
|
|
170
266
|
},
|
|
171
|
-
setValue(val) {
|
|
267
|
+
setValue(val: QueryResult | Promise<void> | Error) {
|
|
172
268
|
currentValue = val;
|
|
173
269
|
},
|
|
174
270
|
getRetainCount() {
|
|
@@ -436,8 +532,14 @@ class QueryResourceImpl {
|
|
|
436
532
|
}
|
|
437
533
|
|
|
438
534
|
_clearCacheEntry = (cacheEntry: QueryResourceCacheEntry): void => {
|
|
439
|
-
|
|
535
|
+
// The new code does this retainCount <= 0 check within SuspenseResource
|
|
536
|
+
// before calling _clearCacheEntry, whereas with the old code we do it here.
|
|
537
|
+
if (RelayFeatureFlags.REFACTOR_SUSPENSE_RESOURCE) {
|
|
440
538
|
this._cache.delete(cacheEntry.cacheIdentifier);
|
|
539
|
+
} else {
|
|
540
|
+
if (cacheEntry.getRetainCount() <= 0) {
|
|
541
|
+
this._cache.delete(cacheEntry.cacheIdentifier);
|
|
542
|
+
}
|
|
441
543
|
}
|
|
442
544
|
};
|
|
443
545
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright (c)
|
|
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.
|
|
@@ -13,14 +13,14 @@
|
|
|
13
13
|
|
|
14
14
|
'use strict';
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
const ReactRelayContext = require('react-relay/ReactRelayContext');
|
|
18
|
-
|
|
16
|
+
import type {IEnvironment} from 'relay-runtime';
|
|
19
17
|
import type {
|
|
20
|
-
IActorEnvironment,
|
|
21
18
|
ActorIdentifier,
|
|
19
|
+
IActorEnvironment,
|
|
22
20
|
} from 'relay-runtime/multi-actor-environment';
|
|
23
|
-
|
|
21
|
+
|
|
22
|
+
const React = require('react');
|
|
23
|
+
const ReactRelayContext = require('react-relay/ReactRelayContext');
|
|
24
24
|
|
|
25
25
|
const {useMemo} = React;
|
|
26
26
|
|
|
@@ -34,10 +34,10 @@ type Props = $ReadOnly<{|
|
|
|
34
34
|
|
|
35
35
|
function RelayEnvironmentProvider(props: Props): React.Node {
|
|
36
36
|
const {children, environment, getEnvironmentForActor} = props;
|
|
37
|
-
const context = useMemo(
|
|
38
|
-
environment,
|
|
39
|
-
getEnvironmentForActor,
|
|
40
|
-
|
|
37
|
+
const context = useMemo(
|
|
38
|
+
() => ({environment, getEnvironmentForActor}),
|
|
39
|
+
[environment, getEnvironmentForActor],
|
|
40
|
+
);
|
|
41
41
|
return (
|
|
42
42
|
<ReactRelayContext.Provider value={context}>
|
|
43
43
|
{children}
|
|
@@ -0,0 +1,115 @@
|
|
|
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
|
+
import type {Disposable, IEnvironment} from 'relay-runtime';
|
|
17
|
+
|
|
18
|
+
const invariant = require('invariant');
|
|
19
|
+
|
|
20
|
+
const TEMPORARY_RETAIN_DURATION_MS = 5 * 60 * 1000;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Allows you to retain a resource as part of a component lifecycle accounting
|
|
24
|
+
* for Suspense. You temporarily retain the resource during render, then
|
|
25
|
+
* permanently retain it during commit and release it during unmount.
|
|
26
|
+
*/
|
|
27
|
+
class SuspenseResource {
|
|
28
|
+
_retainCount = 0;
|
|
29
|
+
_retainDisposable: ?Disposable = null;
|
|
30
|
+
_releaseTemporaryRetain: ?() => void = null;
|
|
31
|
+
_retain: IEnvironment => Disposable;
|
|
32
|
+
|
|
33
|
+
constructor(retain: (environment: IEnvironment) => Disposable) {
|
|
34
|
+
this._retain = (environment: IEnvironment): Disposable => {
|
|
35
|
+
this._retainCount++;
|
|
36
|
+
if (this._retainCount === 1) {
|
|
37
|
+
this._retainDisposable = retain(environment);
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
dispose: () => {
|
|
41
|
+
this._retainCount = Math.max(0, this._retainCount - 1);
|
|
42
|
+
if (this._retainCount === 0) {
|
|
43
|
+
invariant(
|
|
44
|
+
this._retainDisposable != null,
|
|
45
|
+
'Relay: Expected disposable to release query to be defined.' +
|
|
46
|
+
"If you're seeing this, this is likely a bug in Relay.",
|
|
47
|
+
);
|
|
48
|
+
this._retainDisposable.dispose();
|
|
49
|
+
this._retainDisposable = null;
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
temporaryRetain(environment: IEnvironment): Disposable {
|
|
57
|
+
// If we're executing in a server environment, there's no need
|
|
58
|
+
// to create temporary retains, since the component will never commit.
|
|
59
|
+
if (environment.isServer()) {
|
|
60
|
+
return {dispose: () => {}};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// temporaryRetain is called during the render phase. However,
|
|
64
|
+
// given that we can't tell if this render will eventually commit or not,
|
|
65
|
+
// we create a timer to autodispose of this retain in case the associated
|
|
66
|
+
// component never commits.
|
|
67
|
+
// If the component /does/ commit, permanentRetain will clear this timeout
|
|
68
|
+
// and permanently retain the data.
|
|
69
|
+
const retention = this._retain(environment);
|
|
70
|
+
let releaseQueryTimeout = null;
|
|
71
|
+
const releaseTemporaryRetain = () => {
|
|
72
|
+
clearTimeout(releaseQueryTimeout);
|
|
73
|
+
releaseQueryTimeout = null;
|
|
74
|
+
this._releaseTemporaryRetain = null;
|
|
75
|
+
retention.dispose();
|
|
76
|
+
};
|
|
77
|
+
releaseQueryTimeout = setTimeout(
|
|
78
|
+
releaseTemporaryRetain,
|
|
79
|
+
TEMPORARY_RETAIN_DURATION_MS,
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// NOTE: Since temporaryRetain can be called multiple times, we release
|
|
83
|
+
// the previous temporary retain after we re-establish a new one, since
|
|
84
|
+
// we only ever need a single temporary retain until the permanent retain is
|
|
85
|
+
// established.
|
|
86
|
+
// temporaryRetain may be called multiple times by React during the render
|
|
87
|
+
// phase, as well as multiple times by other query components that are
|
|
88
|
+
// rendering the same query/variables.
|
|
89
|
+
this._releaseTemporaryRetain?.();
|
|
90
|
+
this._releaseTemporaryRetain = releaseTemporaryRetain;
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
dispose: () => {
|
|
94
|
+
this._releaseTemporaryRetain?.();
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
permanentRetain(environment: IEnvironment): Disposable {
|
|
100
|
+
const disposable = this._retain(environment);
|
|
101
|
+
this.releaseTemporaryRetain();
|
|
102
|
+
return disposable;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
releaseTemporaryRetain(): void {
|
|
106
|
+
this._releaseTemporaryRetain?.();
|
|
107
|
+
this._releaseTemporaryRetain = null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
getRetainCount(): number {
|
|
111
|
+
return this._retainCount;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
module.exports = SuspenseResource;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright (c)
|
|
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.
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
import type {
|
|
15
15
|
EntryPoint,
|
|
16
|
-
EntryPointProps,
|
|
17
16
|
EntryPointElementConfig,
|
|
17
|
+
EntryPointProps,
|
|
18
18
|
} from '../../EntryPointTypes.flow';
|
|
19
19
|
|
|
20
20
|
type MyComponentOtherProps = $ReadOnly<{|
|
|
@@ -30,10 +30,11 @@ type PreloadParams = $ReadOnly<{||}>;
|
|
|
30
30
|
type MyComponentEntryPointType = EntryPoint<PreloadParams, typeof MyComponent>;
|
|
31
31
|
|
|
32
32
|
// This gets the "other props" of the component through the entrypoint's typing
|
|
33
|
-
type MyComponentEntryPointProps =
|
|
33
|
+
type MyComponentEntryPointProps =
|
|
34
|
+
EntryPointElementConfig<MyComponentEntryPointType>;
|
|
34
35
|
|
|
35
36
|
// This gets the "other props" directly from the component's prop typings
|
|
36
|
-
type OtherProps =
|
|
37
|
+
type OtherProps = MyComponentProps['props'];
|
|
37
38
|
|
|
38
39
|
// We want to make sure that `OtherProps` and `MyComponentEntryPointProps` are exactly the same.
|
|
39
40
|
opaque type __SUBTYPE_CHECK_1__: OtherProps = MyComponentEntryPointProps;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright (c)
|
|
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.
|
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
+
import type {JSResourceReference} from 'JSResourceReference';
|
|
14
15
|
import type {
|
|
15
16
|
EntryPoint,
|
|
16
17
|
EntryPointProps,
|
|
17
18
|
PreloadedEntryPoint,
|
|
18
19
|
} from '../../EntryPointTypes.flow';
|
|
19
|
-
import type {JSResourceReference} from 'JSResourceReference';
|
|
20
20
|
|
|
21
21
|
declare function mockJSResource<TModule>(
|
|
22
22
|
module: TModule,
|
|
@@ -0,0 +1,59 @@
|
|
|
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
|
+
* @generated SignedSource<<57e35620e0558adaa97ee6b06423e705>>
|
|
8
|
+
* @flow
|
|
9
|
+
* @lightSyntaxTransform
|
|
10
|
+
* @nogrep
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/* eslint-disable */
|
|
14
|
+
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
/*::
|
|
18
|
+
import type { Fragment, ReaderFragment } from 'relay-runtime';
|
|
19
|
+
import type { FragmentType } from "relay-runtime";
|
|
20
|
+
declare export opaque type useFragmentFlowtest_user$fragmentType: FragmentType;
|
|
21
|
+
export type useFragmentFlowtest_user$ref = useFragmentFlowtest_user$fragmentType;
|
|
22
|
+
export type useFragmentFlowtest_user$data = {|
|
|
23
|
+
+id: string,
|
|
24
|
+
+$fragmentType: useFragmentFlowtest_user$fragmentType,
|
|
25
|
+
|};
|
|
26
|
+
export type useFragmentFlowtest_user = useFragmentFlowtest_user$data;
|
|
27
|
+
export type useFragmentFlowtest_user$key = {
|
|
28
|
+
+$data?: useFragmentFlowtest_user$data,
|
|
29
|
+
+$fragmentSpreads: useFragmentFlowtest_user$fragmentType,
|
|
30
|
+
...
|
|
31
|
+
};
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
var node/*: ReaderFragment*/ = {
|
|
35
|
+
"argumentDefinitions": [],
|
|
36
|
+
"kind": "Fragment",
|
|
37
|
+
"metadata": null,
|
|
38
|
+
"name": "useFragmentFlowtest_user",
|
|
39
|
+
"selections": [
|
|
40
|
+
{
|
|
41
|
+
"alias": null,
|
|
42
|
+
"args": null,
|
|
43
|
+
"kind": "ScalarField",
|
|
44
|
+
"name": "id",
|
|
45
|
+
"storageKey": null
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"type": "User",
|
|
49
|
+
"abstractKey": null
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
if (__DEV__) {
|
|
53
|
+
(node/*: any*/).hash = "a0eb71a1bbfb0eb3a4c42fb5a69a7f81";
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
module.exports = ((node/*: any*/)/*: Fragment<
|
|
57
|
+
useFragmentFlowtest_user$fragmentType,
|
|
58
|
+
useFragmentFlowtest_user$data,
|
|
59
|
+
>*/);
|
|
@@ -0,0 +1,61 @@
|
|
|
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
|
+
* @generated SignedSource<<e21003870360e15cc93c1cee7aa239ad>>
|
|
8
|
+
* @flow
|
|
9
|
+
* @lightSyntaxTransform
|
|
10
|
+
* @nogrep
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/* eslint-disable */
|
|
14
|
+
|
|
15
|
+
'use strict';
|
|
16
|
+
|
|
17
|
+
/*::
|
|
18
|
+
import type { Fragment, ReaderFragment } from 'relay-runtime';
|
|
19
|
+
import type { FragmentType } from "relay-runtime";
|
|
20
|
+
declare export opaque type useFragmentFlowtest_users$fragmentType: FragmentType;
|
|
21
|
+
export type useFragmentFlowtest_users$ref = useFragmentFlowtest_users$fragmentType;
|
|
22
|
+
export type useFragmentFlowtest_users$data = $ReadOnlyArray<{|
|
|
23
|
+
+id: string,
|
|
24
|
+
+$fragmentType: useFragmentFlowtest_users$fragmentType,
|
|
25
|
+
|}>;
|
|
26
|
+
export type useFragmentFlowtest_users = useFragmentFlowtest_users$data;
|
|
27
|
+
export type useFragmentFlowtest_users$key = $ReadOnlyArray<{
|
|
28
|
+
+$data?: useFragmentFlowtest_users$data,
|
|
29
|
+
+$fragmentSpreads: useFragmentFlowtest_users$fragmentType,
|
|
30
|
+
...
|
|
31
|
+
}>;
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
var node/*: ReaderFragment*/ = {
|
|
35
|
+
"argumentDefinitions": [],
|
|
36
|
+
"kind": "Fragment",
|
|
37
|
+
"metadata": {
|
|
38
|
+
"plural": true
|
|
39
|
+
},
|
|
40
|
+
"name": "useFragmentFlowtest_users",
|
|
41
|
+
"selections": [
|
|
42
|
+
{
|
|
43
|
+
"alias": null,
|
|
44
|
+
"args": null,
|
|
45
|
+
"kind": "ScalarField",
|
|
46
|
+
"name": "id",
|
|
47
|
+
"storageKey": null
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
"type": "User",
|
|
51
|
+
"abstractKey": null
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
if (__DEV__) {
|
|
55
|
+
(node/*: any*/).hash = "8b9b9b23494aec63a7cb96eed58ebcbc";
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
module.exports = ((node/*: any*/)/*: Fragment<
|
|
59
|
+
useFragmentFlowtest_users$fragmentType,
|
|
60
|
+
useFragmentFlowtest_users$data,
|
|
61
|
+
>*/);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright (c)
|
|
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.
|
|
@@ -11,16 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
// flowlint ambiguous-object-type:error
|
|
13
13
|
|
|
14
|
-
import useBlockingPaginationFragment from '../useBlockingPaginationFragment';
|
|
15
14
|
import type {LoadMoreFn} from '../useLoadMoreFunction';
|
|
16
|
-
import {
|
|
17
|
-
fragmentData,
|
|
18
|
-
fragmentInput,
|
|
19
|
-
keyAnotherNonNullable,
|
|
20
|
-
keyAnotherNullable,
|
|
21
|
-
keyNonNullable,
|
|
22
|
-
keyNullable,
|
|
23
|
-
} from './utils';
|
|
24
15
|
import type {
|
|
25
16
|
FetchFn,
|
|
26
17
|
NonNullableData,
|
|
@@ -31,6 +22,16 @@ import type {
|
|
|
31
22
|
} from './utils';
|
|
32
23
|
import type {IEnvironment, OperationType} from 'relay-runtime';
|
|
33
24
|
|
|
25
|
+
import useBlockingPaginationFragment from '../useBlockingPaginationFragment';
|
|
26
|
+
import {
|
|
27
|
+
fragmentData,
|
|
28
|
+
fragmentInput,
|
|
29
|
+
keyAnotherNonNullable,
|
|
30
|
+
keyAnotherNullable,
|
|
31
|
+
keyNonNullable,
|
|
32
|
+
keyNullable,
|
|
33
|
+
} from './utils';
|
|
34
|
+
|
|
34
35
|
type ExpectedReturnType<
|
|
35
36
|
TQuery: OperationType,
|
|
36
37
|
TQueryVariables,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright (c)
|
|
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.
|
|
@@ -11,52 +11,75 @@
|
|
|
11
11
|
|
|
12
12
|
// flowlint ambiguous-object-type:error
|
|
13
13
|
|
|
14
|
-
import useFragment from '../useFragment';
|
|
15
|
-
import {
|
|
16
|
-
fragmentInput,
|
|
17
|
-
keyAnotherNonNullable,
|
|
18
|
-
keyAnotherNullable,
|
|
19
|
-
keyNonNullable,
|
|
20
|
-
keyNonNullablePlural,
|
|
21
|
-
keyNullable,
|
|
22
|
-
keyNullablePlural,
|
|
23
|
-
fragmentData,
|
|
24
|
-
} from './utils';
|
|
25
14
|
import type {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
15
|
+
useFragmentFlowtest_user$data,
|
|
16
|
+
useFragmentFlowtest_user$key,
|
|
17
|
+
} from './__generated__/useFragmentFlowtest_user.graphql';
|
|
18
|
+
import typeof useFragmentFlowtest_user$fragment from './__generated__/useFragmentFlowtest_user.graphql';
|
|
19
|
+
import type {
|
|
20
|
+
useFragmentFlowtest_users$data,
|
|
21
|
+
useFragmentFlowtest_users$key,
|
|
22
|
+
} from './__generated__/useFragmentFlowtest_users.graphql';
|
|
23
|
+
import typeof useFragmentFlowtest_users$fragment from './__generated__/useFragmentFlowtest_users.graphql';
|
|
24
|
+
|
|
25
|
+
import useFragment from '../useFragment';
|
|
26
|
+
import {graphql} from 'relay-runtime';
|
|
27
|
+
|
|
28
|
+
declare var Any: $FlowFixMe;
|
|
29
|
+
|
|
30
|
+
const userFragment: useFragmentFlowtest_user$fragment = graphql`
|
|
31
|
+
fragment useFragmentFlowtest_user on User {
|
|
32
|
+
id
|
|
33
|
+
}
|
|
34
|
+
`;
|
|
35
|
+
|
|
36
|
+
const usersFragment: useFragmentFlowtest_users$fragment = graphql`
|
|
37
|
+
fragment useFragmentFlowtest_users on User @relay(plural: true) {
|
|
38
|
+
id
|
|
39
|
+
}
|
|
40
|
+
`;
|
|
31
41
|
|
|
32
42
|
/* eslint-disable react-hooks/rules-of-hooks */
|
|
33
43
|
|
|
34
44
|
// Nullability of returned data type is correct
|
|
35
|
-
(useFragment(
|
|
36
|
-
|
|
37
|
-
(
|
|
38
|
-
|
|
45
|
+
(useFragment(
|
|
46
|
+
userFragment,
|
|
47
|
+
(Any: useFragmentFlowtest_user$key),
|
|
48
|
+
): useFragmentFlowtest_user$data);
|
|
49
|
+
(useFragment(
|
|
50
|
+
userFragment,
|
|
51
|
+
(Any: ?useFragmentFlowtest_user$key),
|
|
52
|
+
): ?useFragmentFlowtest_user$data);
|
|
53
|
+
(useFragment(
|
|
54
|
+
usersFragment,
|
|
55
|
+
(Any: useFragmentFlowtest_users$key),
|
|
56
|
+
): useFragmentFlowtest_users$data);
|
|
57
|
+
(useFragment(
|
|
58
|
+
usersFragment,
|
|
59
|
+
(Any: ?useFragmentFlowtest_users$key),
|
|
60
|
+
): ?useFragmentFlowtest_users$data);
|
|
39
61
|
|
|
40
62
|
// $FlowExpectedError: can't cast nullable to non-nullable
|
|
41
|
-
(useFragment(
|
|
63
|
+
(useFragment(
|
|
64
|
+
userFragment,
|
|
65
|
+
(Any: ?useFragmentFlowtest_user$key),
|
|
66
|
+
): useFragmentFlowtest_user$data);
|
|
42
67
|
// $FlowExpectedError: can't cast nullable plural to non-nullable plural
|
|
43
|
-
(useFragment(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
// $FlowExpectedError
|
|
48
|
-
(useFragment(fragmentInput, keyAnotherNullable): NullableData);
|
|
68
|
+
(useFragment(
|
|
69
|
+
usersFragment,
|
|
70
|
+
(Any: ?useFragmentFlowtest_users$key),
|
|
71
|
+
): useFragmentFlowtest_users$data);
|
|
49
72
|
|
|
50
73
|
// $FlowExpectedError: Key should be one of the generated types
|
|
51
|
-
|
|
74
|
+
useFragment(userFragment, 'INVALID_KEY');
|
|
52
75
|
|
|
53
76
|
// $FlowExpectedError: Key should not be a user provided object
|
|
54
|
-
useFragment(
|
|
77
|
+
useFragment(userFragment, {a: 123});
|
|
55
78
|
|
|
56
79
|
// $FlowExpectedError: Key should not be an empty object
|
|
57
|
-
useFragment(
|
|
80
|
+
useFragment(userFragment, {});
|
|
58
81
|
|
|
59
82
|
// $FlowExpectedError: Key should be the `<name>$key` type from generated flow
|
|
60
|
-
useFragment(
|
|
83
|
+
useFragment(userFragment, (Any: useFragmentFlowtest_user$data));
|
|
61
84
|
|
|
62
85
|
/* eslint-enable react-hooks/rules-of-hooks */
|