react-relay 20.1.1 → 21.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/ReactRelayContext.js.flow +2 -2
- package/ReactRelayFragmentContainer.js.flow +8 -9
- package/ReactRelayLocalQueryRenderer.js.flow +11 -3
- package/ReactRelayLoggingContext.js.flow +3 -3
- package/ReactRelayPaginationContainer.js.flow +31 -24
- package/ReactRelayQueryFetcher.js.flow +1 -1
- package/ReactRelayQueryRenderer.js.flow +2 -2
- package/ReactRelayQueryRendererContext.js.flow +2 -2
- package/ReactRelayRefetchContainer.js.flow +17 -14
- package/ReactRelayTestMocker.js.flow +10 -10
- package/ReactRelayTypes.js.flow +18 -20
- package/RelayContext.js.flow +3 -3
- package/__flowtests__/ReactRelayFragmentContainer-flowtest.js.flow +11 -11
- package/__flowtests__/ReactRelayPaginationContainer-flowtest.js.flow +5 -5
- package/__flowtests__/ReactRelayRefetchContainer-flowtest.js.flow +5 -5
- package/__flowtests__/RelayModern-flowtest.js.flow +24 -27
- package/__flowtests__/RelayModernFlowtest_users.graphql.js.flow +1 -1
- package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer.graphql.js.flow +3 -4
- package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer2.graphql.js.flow +3 -4
- package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtestQuery.graphql.js.flow +9 -10
- package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtest_viewer.graphql.js.flow +4 -5
- package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtestQuery.graphql.js.flow +9 -10
- package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtest_viewer.graphql.js.flow +4 -5
- package/__flowtests__/__generated__/RelayModernFlowtest_badref.graphql.js.flow +3 -4
- package/__flowtests__/__generated__/RelayModernFlowtest_notref.graphql.js.flow +3 -4
- package/__flowtests__/__generated__/RelayModernFlowtest_user.graphql.js.flow +3 -4
- package/__flowtests__/__generated__/RelayModernFlowtest_users.graphql.js.flow +5 -6
- package/buildReactRelayContainer.js.flow +4 -4
- package/getRootVariablesForFragments.js.flow +1 -1
- package/hooks.js +1 -1
- package/hooks.js.flow +23 -8
- package/index.js +1 -1
- package/index.js.flow +40 -14
- package/isRelayEnvironment.js.flow +1 -1
- package/jest-react/internalAct.js.flow +1 -1
- package/legacy.js +1 -1
- package/legacy.js.flow +32 -13
- package/lib/ReactRelayFragmentContainer.js +1 -1
- package/lib/ReactRelayPaginationContainer.js +8 -8
- package/lib/ReactRelayRefetchContainer.js +8 -8
- package/lib/ReactRelayTestMocker.js +5 -5
- package/lib/hooks.js +18 -8
- package/lib/index.js +30 -14
- package/lib/legacy.js +26 -13
- package/lib/relay-hooks/legacy/useBlockingPaginationFragment.js +5 -5
- package/lib/relay-hooks/legacy/useRefetchableFragmentNode.js +34 -34
- package/lib/relay-hooks/loadEntryPoint.js +2 -2
- package/lib/relay-hooks/loadQuery.js +14 -14
- package/lib/relay-hooks/preloadQuery_DEPRECATED.js +10 -10
- package/lib/relay-hooks/readFragmentInternal.js +6 -6
- package/lib/relay-hooks/rsc/serverFetchQuery.js +20 -0
- package/lib/relay-hooks/rsc/serverPreloadQuery.js +31 -0
- package/lib/relay-hooks/rsc/serverReadFragment.js +15 -0
- package/lib/relay-hooks/rsc/useQueryFromServer.js +62 -0
- package/lib/relay-hooks/useFragmentInternal_CURRENT.js +49 -25
- package/lib/relay-hooks/useFragmentInternal_EXPERIMENTAL.js +81 -44
- package/lib/relay-hooks/useLazyLoadQueryNode.js +32 -19
- package/lib/relay-hooks/useMutation.js +6 -14
- package/lib/relay-hooks/useMutationAction_EXPERIMENTAL.js +26 -0
- package/lib/relay-hooks/usePreloadedQuery.js +52 -47
- package/lib/relay-hooks/useQueryLoader.js +2 -2
- package/lib/relay-hooks/useQueryLoader_EXPERIMENTAL.js +2 -2
- package/lib/relay-hooks/useRefetchableFragmentInternal.js +31 -31
- package/lib/rsc-client_EXPERIMENTAL.js +7 -0
- package/lib/rsc_EXPERIMENTAL.js +43 -0
- package/multi-actor/ActorChange.js.flow +1 -1
- package/package.json +3 -2
- package/relay-hooks/EntryPointContainer.react.js.flow +6 -6
- package/relay-hooks/EntryPointTypes.flow.js.flow +61 -67
- package/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js.flow +23 -21
- package/relay-hooks/MatchContainer.js.flow +12 -6
- package/relay-hooks/NestedRelayEntryPointBuilderUtils.js.flow +3 -9
- package/relay-hooks/QueryResource.js.flow +6 -6
- package/relay-hooks/RelayEnvironmentProvider.js.flow +2 -2
- package/relay-hooks/__flowtests__/EntryPointTypes/EntryPointElementConfig-flowtest.js.flow +6 -6
- package/relay-hooks/__flowtests__/EntryPointTypes/ExtractQueryTypes-flowtest.js.flow +48 -1
- package/relay-hooks/__flowtests__/EntryPointTypes/NestedEntrypoints-flowtest.js.flow +9 -9
- package/relay-hooks/__flowtests__/__generated__/useFragmentFlowtest_user.graphql.js.flow +3 -4
- package/relay-hooks/__flowtests__/__generated__/useFragmentFlowtest_users.graphql.js.flow +5 -6
- package/relay-hooks/__flowtests__/useBlockingPaginationFragment-flowtest.js.flow +27 -32
- package/relay-hooks/__flowtests__/useFragment-flowtest.js.flow +25 -25
- package/relay-hooks/__flowtests__/usePaginationFragment-flowtest.js.flow +26 -32
- package/relay-hooks/__flowtests__/useRefetchableFragment-flowtest.js.flow +23 -30
- package/relay-hooks/__flowtests__/utils.js.flow +4 -4
- package/relay-hooks/getConnectionState.js.flow +2 -2
- package/relay-hooks/legacy/FragmentResource.js.flow +13 -13
- package/relay-hooks/legacy/useBlockingPaginationFragment.js.flow +24 -25
- package/relay-hooks/legacy/useFragmentNode.js.flow +4 -4
- package/relay-hooks/legacy/useRefetchableFragmentNode.js.flow +79 -81
- package/relay-hooks/loadEntryPoint.js.flow +15 -13
- package/relay-hooks/loadQuery.js.flow +18 -18
- package/relay-hooks/preloadQuery_DEPRECATED.js.flow +16 -13
- package/relay-hooks/prepareEntryPoint_DEPRECATED.js.flow +7 -7
- package/relay-hooks/readFragmentInternal.js.flow +9 -9
- package/relay-hooks/rsc/serverFetchQuery.js.flow +31 -0
- package/relay-hooks/rsc/serverPreloadQuery.js.flow +69 -0
- package/relay-hooks/rsc/serverReadFragment.js.flow +33 -0
- package/relay-hooks/rsc/useQueryFromServer.js.flow +135 -0
- package/relay-hooks/useClientQuery.js.flow +2 -2
- package/relay-hooks/useEntryPointLoader.js.flow +11 -11
- package/relay-hooks/useFragment.js.flow +7 -7
- package/relay-hooks/useFragmentInternal.js.flow +1 -1
- package/relay-hooks/useFragmentInternal_CURRENT.js.flow +54 -22
- package/relay-hooks/useFragmentInternal_EXPERIMENTAL.js.flow +95 -46
- package/relay-hooks/useIsOperationNodeActive.js.flow +1 -1
- package/relay-hooks/useIsParentQueryActive.js.flow +1 -1
- package/relay-hooks/useLazyLoadQuery.js.flow +10 -3
- package/relay-hooks/useLazyLoadQueryNode.js.flow +67 -28
- package/relay-hooks/useLoadMoreFunction.js.flow +7 -6
- package/relay-hooks/useLoadMoreFunction_EXPERIMENTAL.js.flow +5 -5
- package/relay-hooks/useMemoVariables.js.flow +1 -1
- package/relay-hooks/useMutation.js.flow +8 -16
- package/relay-hooks/useMutationAction_EXPERIMENTAL.js.flow +68 -0
- package/relay-hooks/usePaginationFragment.js.flow +15 -11
- package/relay-hooks/usePrefetchableForwardPaginationFragment.js.flow +19 -18
- package/relay-hooks/usePrefetchableForwardPaginationFragment_EXPERIMENTAL.js.flow +19 -18
- package/relay-hooks/usePreloadedQuery.js.flow +119 -85
- package/relay-hooks/useQueryLoader.js.flow +27 -23
- package/relay-hooks/useQueryLoader_EXPERIMENTAL.js.flow +10 -10
- package/relay-hooks/useRefetchableFragment.js.flow +16 -11
- package/relay-hooks/useRefetchableFragmentInternal.js.flow +77 -79
- package/relay-hooks/useRelayLoggingContext.js.flow +1 -1
- package/relay-hooks/useSubscribeToInvalidationState.js.flow +1 -1
- package/relay-hooks/useSubscription.js.flow +1 -1
- package/rsc-client_EXPERIMENTAL.js +10 -0
- package/rsc-client_EXPERIMENTAL.js.flow +23 -0
- package/rsc_EXPERIMENTAL.js +10 -0
- package/rsc_EXPERIMENTAL.js.flow +90 -0
|
@@ -41,10 +41,10 @@ type FragmentQueryOptions = {
|
|
|
41
41
|
networkCacheConfig?: ?CacheConfig,
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
-
type FragmentState =
|
|
44
|
+
type FragmentState = Readonly<
|
|
45
45
|
| {kind: 'bailout'}
|
|
46
46
|
| {kind: 'singular', snapshot: Snapshot, epoch: number}
|
|
47
|
-
| {kind: 'plural', snapshots:
|
|
47
|
+
| {kind: 'plural', snapshots: ReadonlyArray<Snapshot>, epoch: number},
|
|
48
48
|
>;
|
|
49
49
|
|
|
50
50
|
function isMissingData(state: FragmentState): boolean {
|
|
@@ -59,7 +59,7 @@ function isMissingData(state: FragmentState): boolean {
|
|
|
59
59
|
|
|
60
60
|
function getMissingClientEdges(
|
|
61
61
|
state: FragmentState,
|
|
62
|
-
):
|
|
62
|
+
): ReadonlyArray<MissingClientEdgeRequestInfo> | null {
|
|
63
63
|
if (state.kind === 'bailout') {
|
|
64
64
|
return null;
|
|
65
65
|
} else if (state.kind === 'singular') {
|
|
@@ -94,7 +94,7 @@ function handlePotentialSnapshotErrorsForState(
|
|
|
94
94
|
function handleMissingClientEdge(
|
|
95
95
|
environment: IEnvironment,
|
|
96
96
|
parentFragmentNode: ReaderFragment,
|
|
97
|
-
parentFragmentRef:
|
|
97
|
+
parentFragmentRef: unknown,
|
|
98
98
|
missingClientEdgeRequestInfo: MissingClientEdgeRequestInfo,
|
|
99
99
|
queryOptions?: FragmentQueryOptions,
|
|
100
100
|
): QueryResult {
|
|
@@ -134,16 +134,16 @@ function getFragmentState(
|
|
|
134
134
|
return {kind: 'bailout'};
|
|
135
135
|
} else {
|
|
136
136
|
return {
|
|
137
|
+
epoch: environment.getStore().getEpoch(),
|
|
137
138
|
kind: 'plural',
|
|
138
139
|
snapshots: fragmentSelector.selectors.map(s => environment.lookup(s)),
|
|
139
|
-
epoch: environment.getStore().getEpoch(),
|
|
140
140
|
};
|
|
141
141
|
}
|
|
142
142
|
} else {
|
|
143
143
|
return {
|
|
144
|
+
epoch: environment.getStore().getEpoch(),
|
|
144
145
|
kind: 'singular',
|
|
145
146
|
snapshot: environment.lookup(fragmentSelector),
|
|
146
|
-
epoch: environment.getStore().getEpoch(),
|
|
147
147
|
};
|
|
148
148
|
}
|
|
149
149
|
}
|
|
@@ -152,7 +152,7 @@ function getFragmentState(
|
|
|
152
152
|
function readFragmentInternal(
|
|
153
153
|
environment: IEnvironment,
|
|
154
154
|
fragmentNode: ReaderFragment,
|
|
155
|
-
fragmentRef:
|
|
155
|
+
fragmentRef: unknown,
|
|
156
156
|
hookDisplayName: string,
|
|
157
157
|
queryOptions?: FragmentQueryOptions,
|
|
158
158
|
fragmentKey?: string,
|
|
@@ -220,7 +220,7 @@ function readFragmentInternal(
|
|
|
220
220
|
) {
|
|
221
221
|
const missingClientEdges = getMissingClientEdges(state);
|
|
222
222
|
if (missingClientEdges?.length) {
|
|
223
|
-
clientEdgeQueries =
|
|
223
|
+
clientEdgeQueries = [] as Array<QueryResult>;
|
|
224
224
|
for (const edge of missingClientEdges) {
|
|
225
225
|
clientEdgeQueries.push(
|
|
226
226
|
handleMissingClientEdge(
|
|
@@ -288,7 +288,7 @@ function readFragmentInternal(
|
|
|
288
288
|
}
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
-
return {
|
|
291
|
+
return {clientEdgeQueries, data};
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
module.exports = readFragmentInternal;
|
|
@@ -0,0 +1,31 @@
|
|
|
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 {IEnvironment, Query, Variables} from 'relay-runtime';
|
|
15
|
+
|
|
16
|
+
const {fetchQuery} = require('relay-runtime');
|
|
17
|
+
|
|
18
|
+
async function serverFetchQuery<TVariables extends Variables, TData>(
|
|
19
|
+
environment: IEnvironment,
|
|
20
|
+
query: Query<TVariables, TData>,
|
|
21
|
+
variables: TVariables,
|
|
22
|
+
): Promise<TData> {
|
|
23
|
+
const observable = fetchQuery(environment, query, variables);
|
|
24
|
+
const result = await observable.toPromise();
|
|
25
|
+
if (result == null) {
|
|
26
|
+
throw new Error('Unexpected null response from fetchQuery');
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = serverFetchQuery;
|
|
@@ -0,0 +1,69 @@
|
|
|
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 {IEnvironment, PayloadError, Query, Variables} from 'relay-runtime';
|
|
15
|
+
|
|
16
|
+
const invariant = require('invariant');
|
|
17
|
+
const {createOperationDescriptor, getRequest} = require('relay-runtime');
|
|
18
|
+
|
|
19
|
+
export type PreloadedQueryResponse<TData> = {
|
|
20
|
+
+data: TData,
|
|
21
|
+
+errors?: ReadonlyArray<PayloadError>,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type PreloadedQueryRef<TVariables, TData> = {
|
|
25
|
+
+kind: 'PreloadedQueryRef',
|
|
26
|
+
+queryId: string,
|
|
27
|
+
+variables: TVariables,
|
|
28
|
+
+_response: Promise<PreloadedQueryResponse<TData>>,
|
|
29
|
+
+fetchedAt: number,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
function serverPreloadQuery<TVariables extends Variables, TData>(
|
|
33
|
+
environment: IEnvironment,
|
|
34
|
+
query: Query<TVariables, TData>,
|
|
35
|
+
variables: TVariables,
|
|
36
|
+
): PreloadedQueryRef<TVariables, TData> {
|
|
37
|
+
const request = getRequest(query);
|
|
38
|
+
const operationDescriptor = createOperationDescriptor(request, variables);
|
|
39
|
+
|
|
40
|
+
const observable = environment.execute({operation: operationDescriptor});
|
|
41
|
+
|
|
42
|
+
const queryId =
|
|
43
|
+
request.params.id ?? request.params.cacheID ?? request.params.name;
|
|
44
|
+
|
|
45
|
+
const response: Promise<PreloadedQueryResponse<TData>> =
|
|
46
|
+
// $FlowFixMe[incompatible-type] PayloadData -> TData; shape validated by the Relay compiler
|
|
47
|
+
observable.toPromise().then(rawResponse => {
|
|
48
|
+
invariant(rawResponse != null, 'Unexpected null response from execute');
|
|
49
|
+
// TODO: @defer returns batched responses; this only handles the first payload
|
|
50
|
+
invariant(
|
|
51
|
+
!Array.isArray(rawResponse),
|
|
52
|
+
'@defer is not yet supported in serverPreloadQuery',
|
|
53
|
+
);
|
|
54
|
+
return {
|
|
55
|
+
data: rawResponse.data,
|
|
56
|
+
errors: rawResponse.errors,
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
kind: 'PreloadedQueryRef',
|
|
62
|
+
queryId,
|
|
63
|
+
variables,
|
|
64
|
+
_response: response,
|
|
65
|
+
fetchedAt: Date.now(),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = serverPreloadQuery;
|
|
@@ -0,0 +1,33 @@
|
|
|
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 {Fragment, FragmentType, IEnvironment} from 'relay-runtime';
|
|
15
|
+
|
|
16
|
+
const {waitForFragmentData} = require('relay-runtime/experimental');
|
|
17
|
+
|
|
18
|
+
type HasSpread<TFragmentType> = {
|
|
19
|
+
+$fragmentSpreads: TFragmentType,
|
|
20
|
+
...
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
async function serverReadFragment<TFragmentType extends FragmentType, TData>(
|
|
24
|
+
environment: IEnvironment,
|
|
25
|
+
fragment: Fragment<TFragmentType, TData>,
|
|
26
|
+
fragmentRef:
|
|
27
|
+
| HasSpread<TFragmentType>
|
|
28
|
+
| ReadonlyArray<HasSpread<TFragmentType>>,
|
|
29
|
+
): Promise<TData> {
|
|
30
|
+
return waitForFragmentData(environment, fragment, fragmentRef);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = serverReadFragment;
|
|
@@ -0,0 +1,135 @@
|
|
|
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 client';
|
|
13
|
+
'use strict';
|
|
14
|
+
|
|
15
|
+
import type {
|
|
16
|
+
PreloadedQueryRef,
|
|
17
|
+
PreloadedQueryResponse,
|
|
18
|
+
} from './serverPreloadQuery';
|
|
19
|
+
import type {Query, Variables} from 'relay-runtime';
|
|
20
|
+
|
|
21
|
+
const usePreloadedQuery = require('../usePreloadedQuery');
|
|
22
|
+
const useRelayEnvironment = require('../useRelayEnvironment');
|
|
23
|
+
// $FlowFixMe[missing-export] React.use is available in React 19+
|
|
24
|
+
const {use, useMemo} = require('react');
|
|
25
|
+
const {
|
|
26
|
+
__internal,
|
|
27
|
+
ROOT_TYPE,
|
|
28
|
+
createOperationDescriptor,
|
|
29
|
+
getRequest,
|
|
30
|
+
} = require('relay-runtime');
|
|
31
|
+
|
|
32
|
+
const {defaultGetDataID, normalizeResponse} = __internal;
|
|
33
|
+
|
|
34
|
+
// $FlowFixMe[unclear-type] WeakSet used for identity-based dedup only
|
|
35
|
+
const committedRefs: WeakSet<any> = new WeakSet();
|
|
36
|
+
|
|
37
|
+
const DEFAULT_STALE_MS = 30_000;
|
|
38
|
+
|
|
39
|
+
function useQueryFromServer<TVariables extends Variables, TData>(
|
|
40
|
+
query: Query<TVariables, TData>,
|
|
41
|
+
queryRef: PreloadedQueryRef<TVariables, TData>,
|
|
42
|
+
options?: {staleThresholdMs?: number},
|
|
43
|
+
): TData {
|
|
44
|
+
const environment = useRelayEnvironment();
|
|
45
|
+
const request = getRequest(query);
|
|
46
|
+
const threshold = options?.staleThresholdMs ?? DEFAULT_STALE_MS;
|
|
47
|
+
// TODO: Add a method to IEnvironment for server-side publish so custom
|
|
48
|
+
// IEnvironment implementations don't need to access _getDataID.
|
|
49
|
+
// $FlowFixMe[prop-missing] _getDataID is not on IEnvironment
|
|
50
|
+
// $FlowFixMe[unclear-type]
|
|
51
|
+
const getDataID: any = environment._getDataID ?? defaultGetDataID;
|
|
52
|
+
|
|
53
|
+
const response: PreloadedQueryResponse<TData> = use(queryRef._response);
|
|
54
|
+
|
|
55
|
+
const isFresh =
|
|
56
|
+
response.data != null && Date.now() - queryRef.fetchedAt <= threshold;
|
|
57
|
+
|
|
58
|
+
const shouldCommit = isFresh && !committedRefs.has(queryRef);
|
|
59
|
+
|
|
60
|
+
// Publish server data to the Relay store without notifying subscribers.
|
|
61
|
+
// This avoids the React "Cannot update a component while rendering a
|
|
62
|
+
// different component" error that occurs when store.notify() triggers
|
|
63
|
+
// setState in other mounted components that subscribe to overlapping records.
|
|
64
|
+
if (shouldCommit) {
|
|
65
|
+
committedRefs.add(queryRef);
|
|
66
|
+
|
|
67
|
+
const operation = createOperationDescriptor(request, queryRef.variables);
|
|
68
|
+
|
|
69
|
+
// $FlowFixMe[unclear-type]
|
|
70
|
+
const responsePayload: any = {
|
|
71
|
+
data: response.data,
|
|
72
|
+
errors: response.errors,
|
|
73
|
+
};
|
|
74
|
+
const relayPayload = normalizeResponse(
|
|
75
|
+
responsePayload,
|
|
76
|
+
operation.root,
|
|
77
|
+
ROOT_TYPE,
|
|
78
|
+
{
|
|
79
|
+
getDataID,
|
|
80
|
+
treatMissingFieldsAsNull: false,
|
|
81
|
+
deferDeduplicatedFields: false,
|
|
82
|
+
// $FlowFixMe[prop-missing]
|
|
83
|
+
log: environment.__log ?? null,
|
|
84
|
+
path: [],
|
|
85
|
+
shouldProcessClientComponents: false,
|
|
86
|
+
},
|
|
87
|
+
false,
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
environment.getStore().publish(relayPayload.source);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Build a PreloadedQuery shim. Fresh data was committed to the store
|
|
94
|
+
// above, so source is null and fetchPolicy is "store-or-network".
|
|
95
|
+
// Stale path uses "network-only" to trigger a client-side refetch.
|
|
96
|
+
const preloadedQuery = useMemo(() => {
|
|
97
|
+
const isFreshAtMemo =
|
|
98
|
+
response.data != null && Date.now() - queryRef.fetchedAt <= threshold;
|
|
99
|
+
|
|
100
|
+
// If this queryRef was already committed to the store by a previous
|
|
101
|
+
// component instance, read from the store even if the server timestamp
|
|
102
|
+
// is past the staleness threshold. This prevents a network refetch
|
|
103
|
+
// from overwriting store mutations made after the initial commit.
|
|
104
|
+
const useStore = isFreshAtMemo || committedRefs.has(queryRef);
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
kind: 'PreloadedQuery_DEPRECATED',
|
|
108
|
+
environment,
|
|
109
|
+
fetchKey: queryRef.fetchedAt,
|
|
110
|
+
fetchPolicy: useStore ? 'store-or-network' : 'network-only',
|
|
111
|
+
id: request.params.id ?? request.params.name,
|
|
112
|
+
name: request.params.name,
|
|
113
|
+
source: null,
|
|
114
|
+
variables: queryRef.variables,
|
|
115
|
+
};
|
|
116
|
+
}, [
|
|
117
|
+
environment,
|
|
118
|
+
queryRef.fetchedAt,
|
|
119
|
+
response.data,
|
|
120
|
+
queryRef.variables,
|
|
121
|
+
request.params.id,
|
|
122
|
+
request.params.name,
|
|
123
|
+
threshold,
|
|
124
|
+
]);
|
|
125
|
+
|
|
126
|
+
// usePreloadedQuery expects an opaque PreloadedQuery that can only be
|
|
127
|
+
// created via loadQuery/useQueryLoader. There's no public API to create
|
|
128
|
+
// one from server-fetched data, so we construct a plain object with the
|
|
129
|
+
// fields usePreloadedQuery reads internally.
|
|
130
|
+
// $FlowFixMe[incompatible-call]
|
|
131
|
+
// $FlowFixMe[incompatible-type]
|
|
132
|
+
return usePreloadedQuery(query, preloadedQuery);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
module.exports = useQueryFromServer;
|
|
@@ -20,9 +20,9 @@ const useLazyLoadQuery = require('./useLazyLoadQuery');
|
|
|
20
20
|
* These queries are consist of queries for client-only data,
|
|
21
21
|
* schematized via local schema extensions and/or Relay resolvers.
|
|
22
22
|
*/
|
|
23
|
-
hook useClientQuery<TVariables
|
|
23
|
+
hook useClientQuery<TVariables extends Variables, TData, TRawResponse>(
|
|
24
24
|
gqlQuery: ClientQuery<TVariables, TData, TRawResponse>,
|
|
25
|
-
variables: TVariables
|
|
25
|
+
variables: NoInfer<TVariables>,
|
|
26
26
|
options?: {
|
|
27
27
|
UNSTABLE_renderPolicy?: RenderPolicy,
|
|
28
28
|
},
|
|
@@ -25,12 +25,12 @@ const useIsMountedRef = require('./useIsMountedRef');
|
|
|
25
25
|
const {useCallback, useEffect, useRef, useState} = require('react');
|
|
26
26
|
|
|
27
27
|
type UseEntryPointLoaderHookReturnType<
|
|
28
|
-
TEntryPointParams
|
|
29
|
-
TPreloadedQueries
|
|
30
|
-
TPreloadedEntryPoints
|
|
31
|
-
TRuntimeProps
|
|
28
|
+
TEntryPointParams extends {...},
|
|
29
|
+
TPreloadedQueries extends {...},
|
|
30
|
+
TPreloadedEntryPoints extends {...},
|
|
31
|
+
TRuntimeProps extends {...},
|
|
32
32
|
TExtraProps,
|
|
33
|
-
TEntryPointComponent
|
|
33
|
+
TEntryPointComponent extends EntryPointComponent<
|
|
34
34
|
TPreloadedQueries,
|
|
35
35
|
TPreloadedEntryPoints,
|
|
36
36
|
TRuntimeProps,
|
|
@@ -53,19 +53,19 @@ const initialNullEntryPointReferenceState: NullEntryPointReference = {
|
|
|
53
53
|
};
|
|
54
54
|
|
|
55
55
|
hook useLoadEntryPoint<
|
|
56
|
-
TEntryPointParams
|
|
56
|
+
TEntryPointParams extends {...},
|
|
57
57
|
// $FlowExpectedError[unclear-type] Need any to make it supertype of all PreloadedQuery
|
|
58
|
-
TPreloadedQueries
|
|
59
|
-
TPreloadedEntryPoints
|
|
60
|
-
TRuntimeProps
|
|
58
|
+
TPreloadedQueries extends {+[string]: PreloadedQuery<any>},
|
|
59
|
+
TPreloadedEntryPoints extends {...},
|
|
60
|
+
TRuntimeProps extends {...},
|
|
61
61
|
TExtraProps,
|
|
62
|
-
TEntryPointComponent
|
|
62
|
+
TEntryPointComponent extends EntryPointComponent<
|
|
63
63
|
TPreloadedQueries,
|
|
64
64
|
TPreloadedEntryPoints,
|
|
65
65
|
TRuntimeProps,
|
|
66
66
|
TExtraProps,
|
|
67
67
|
>,
|
|
68
|
-
TEntryPoint
|
|
68
|
+
TEntryPoint extends EntryPoint<TEntryPointParams, TEntryPointComponent>,
|
|
69
69
|
>(
|
|
70
70
|
environmentProvider: IEnvironmentProvider<EnvironmentProviderOptions>,
|
|
71
71
|
entryPoint: TEntryPoint,
|
|
@@ -24,30 +24,30 @@ type HasSpread<TFragmentType> = {
|
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
// if the key is non-nullable, return non-nullable value
|
|
27
|
-
declare hook useFragment<TFragmentType
|
|
27
|
+
declare hook useFragment<TFragmentType extends FragmentType, TData>(
|
|
28
28
|
fragment: Fragment<TFragmentType, TData>,
|
|
29
29
|
key: HasSpread<TFragmentType>,
|
|
30
30
|
): TData;
|
|
31
31
|
|
|
32
32
|
// if the key is nullable, return nullable value
|
|
33
|
-
declare hook useFragment<TFragmentType
|
|
33
|
+
declare hook useFragment<TFragmentType extends FragmentType, TData>(
|
|
34
34
|
fragment: Fragment<TFragmentType, TData>,
|
|
35
35
|
key: ?HasSpread<TFragmentType>,
|
|
36
36
|
): ?TData;
|
|
37
37
|
|
|
38
38
|
// if the key is a non-nullable array of keys, return non-nullable array
|
|
39
|
-
declare hook useFragment<TFragmentType
|
|
39
|
+
declare hook useFragment<TFragmentType extends FragmentType, TData>(
|
|
40
40
|
fragment: Fragment<TFragmentType, TData>,
|
|
41
|
-
key:
|
|
41
|
+
key: ReadonlyArray<HasSpread<TFragmentType>>,
|
|
42
42
|
): TData;
|
|
43
43
|
|
|
44
44
|
// if the key is a nullable array of keys, return nullable array
|
|
45
|
-
declare hook useFragment<TFragmentType
|
|
45
|
+
declare hook useFragment<TFragmentType extends FragmentType, TData>(
|
|
46
46
|
fragment: Fragment<TFragmentType, TData>,
|
|
47
|
-
key:
|
|
47
|
+
key: ?ReadonlyArray<HasSpread<TFragmentType>>,
|
|
48
48
|
): ?TData;
|
|
49
49
|
|
|
50
|
-
hook useFragment(fragment: GraphQLTaggedNode, key:
|
|
50
|
+
hook useFragment(fragment: GraphQLTaggedNode, key: unknown): unknown {
|
|
51
51
|
const fragmentNode = getFragment(fragment);
|
|
52
52
|
useStaticFragmentNodeWarning(fragmentNode, 'first argument of useFragment()');
|
|
53
53
|
const data = useFragmentInternal(fragmentNode, key, 'useFragment()');
|
|
@@ -20,7 +20,7 @@ import {RelayFeatureFlags} from 'relay-runtime';
|
|
|
20
20
|
|
|
21
21
|
hook useFragmentInternal(
|
|
22
22
|
fragmentNode: ReaderFragment,
|
|
23
|
-
fragmentRef:
|
|
23
|
+
fragmentRef: unknown,
|
|
24
24
|
hookDisplayName: string,
|
|
25
25
|
queryOptions?: FragmentQueryOptions,
|
|
26
26
|
): ?SelectorData | Array<?SelectorData> {
|