react-relay 17.0.0 → 18.1.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/ReactRelayContainerUtils.js.flow +2 -2
- package/ReactRelayContext.js +1 -1
- package/ReactRelayContext.js.flow +1 -1
- package/ReactRelayFragmentContainer.js.flow +2 -2
- package/ReactRelayPaginationContainer.js.flow +2 -2
- package/ReactRelayQueryRenderer.js.flow +1 -1
- package/ReactRelayQueryRendererContext.js.flow +1 -1
- package/ReactRelayRefetchContainer.js.flow +2 -2
- package/ReactRelayTypes.js.flow +45 -18
- package/__flowtests__/ReactRelayFragmentContainer-flowtest.js.flow +2 -2
- package/buildReactRelayContainer.js.flow +6 -5
- package/hooks.js +1 -1
- package/index.js +1 -1
- package/legacy.js +1 -1
- package/lib/relay-hooks/getConnectionState.js +47 -0
- package/lib/relay-hooks/legacy/FragmentResource.js +2 -6
- package/lib/relay-hooks/loadEntryPoint.js +8 -5
- package/lib/relay-hooks/loadQuery.js +2 -14
- package/lib/relay-hooks/readFragmentInternal.js +2 -4
- package/lib/relay-hooks/useEntryPointLoader.js +5 -8
- package/lib/relay-hooks/useFragment.js +4 -7
- package/lib/relay-hooks/useFragmentInternal.js +6 -484
- package/lib/relay-hooks/useFragmentInternal_CURRENT.js +477 -0
- package/lib/relay-hooks/useFragmentInternal_EXPERIMENTAL.js +499 -0
- package/lib/relay-hooks/useLazyLoadQuery.js +2 -5
- package/lib/relay-hooks/useLoadMoreFunction.js +10 -43
- package/lib/relay-hooks/useLoadMoreFunction_EXPERIMENTAL.js +130 -0
- package/lib/relay-hooks/usePreloadedQuery.js +6 -9
- package/lib/relay-hooks/useQueryLoader.js +9 -3
- package/lib/relay-hooks/useQueryLoader_EXPERIMENTAL.js +120 -0
- package/multi-actor/ActorChange.js.flow +1 -1
- 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 +1 -1
- package/react-relay-legacy.min.js +1 -1
- package/react-relay.js +2 -2
- package/react-relay.min.js +2 -2
- package/relay-hooks/EntryPointTypes.flow.js.flow +35 -12
- package/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js.flow +8 -4
- package/relay-hooks/MatchContainer.js.flow +1 -1
- package/relay-hooks/ProfilerContext.js.flow +1 -1
- package/relay-hooks/__flowtests__/EntryPointTypes/ExtractQueryTypes-flowtest.js.flow +43 -0
- package/relay-hooks/getConnectionState.js.flow +97 -0
- package/relay-hooks/legacy/FragmentResource.js.flow +2 -13
- package/relay-hooks/loadEntryPoint.js.flow +10 -4
- package/relay-hooks/loadQuery.js.flow +4 -28
- package/relay-hooks/prepareEntryPoint_DEPRECATED.js.flow +4 -1
- package/relay-hooks/readFragmentInternal.js.flow +1 -10
- package/relay-hooks/useEntryPointLoader.js.flow +3 -4
- package/relay-hooks/useFragment.js.flow +0 -5
- package/relay-hooks/useFragmentInternal.js.flow +19 -643
- package/relay-hooks/useFragmentInternal_CURRENT.js.flow +656 -0
- package/relay-hooks/useFragmentInternal_EXPERIMENTAL.js.flow +718 -0
- package/relay-hooks/useLazyLoadQuery.js.flow +0 -5
- package/relay-hooks/useLoadMoreFunction.js.flow +14 -80
- package/relay-hooks/useLoadMoreFunction_EXPERIMENTAL.js.flow +280 -0
- package/relay-hooks/usePaginationFragment.js.flow +1 -1
- package/relay-hooks/usePreloadedQuery.js.flow +0 -5
- package/relay-hooks/useQueryLoader.js.flow +28 -5
- package/relay-hooks/useQueryLoader_EXPERIMENTAL.js.flow +253 -0
@@ -0,0 +1,97 @@
|
|
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 {Direction, ReaderFragment} from 'relay-runtime';
|
15
|
+
|
16
|
+
const invariant = require('invariant');
|
17
|
+
const {ConnectionInterface, getValueAtPath} = require('relay-runtime');
|
18
|
+
|
19
|
+
function getConnectionState(
|
20
|
+
direction: Direction,
|
21
|
+
fragmentNode: ReaderFragment,
|
22
|
+
fragmentData: mixed,
|
23
|
+
connectionPathInFragmentData: $ReadOnlyArray<string | number>,
|
24
|
+
): {
|
25
|
+
cursor: ?string,
|
26
|
+
hasMore: boolean,
|
27
|
+
} {
|
28
|
+
const {
|
29
|
+
EDGES,
|
30
|
+
PAGE_INFO,
|
31
|
+
HAS_NEXT_PAGE,
|
32
|
+
HAS_PREV_PAGE,
|
33
|
+
END_CURSOR,
|
34
|
+
START_CURSOR,
|
35
|
+
} = ConnectionInterface.get();
|
36
|
+
const connection = getValueAtPath(fragmentData, connectionPathInFragmentData);
|
37
|
+
if (connection == null) {
|
38
|
+
return {cursor: null, hasMore: false};
|
39
|
+
}
|
40
|
+
|
41
|
+
invariant(
|
42
|
+
typeof connection === 'object',
|
43
|
+
'Relay: Expected connection in fragment `%s` to have been `null`, or ' +
|
44
|
+
'a plain object with %s and %s properties. Instead got `%s`.',
|
45
|
+
fragmentNode.name,
|
46
|
+
EDGES,
|
47
|
+
PAGE_INFO,
|
48
|
+
connection,
|
49
|
+
);
|
50
|
+
|
51
|
+
const edges = connection[EDGES];
|
52
|
+
const pageInfo = connection[PAGE_INFO];
|
53
|
+
if (edges == null || pageInfo == null) {
|
54
|
+
return {cursor: null, hasMore: false};
|
55
|
+
}
|
56
|
+
|
57
|
+
invariant(
|
58
|
+
Array.isArray(edges),
|
59
|
+
'Relay: Expected connection in fragment `%s` to have a plural `%s` field. ' +
|
60
|
+
'Instead got `%s`.',
|
61
|
+
fragmentNode.name,
|
62
|
+
EDGES,
|
63
|
+
edges,
|
64
|
+
);
|
65
|
+
invariant(
|
66
|
+
typeof pageInfo === 'object',
|
67
|
+
'Relay: Expected connection in fragment `%s` to have a `%s` field. ' +
|
68
|
+
'Instead got `%s`.',
|
69
|
+
fragmentNode.name,
|
70
|
+
PAGE_INFO,
|
71
|
+
pageInfo,
|
72
|
+
);
|
73
|
+
|
74
|
+
const cursor =
|
75
|
+
direction === 'forward'
|
76
|
+
? pageInfo[END_CURSOR] ?? null
|
77
|
+
: pageInfo[START_CURSOR] ?? null;
|
78
|
+
invariant(
|
79
|
+
cursor === null || typeof cursor === 'string',
|
80
|
+
'Relay: Expected page info for connection in fragment `%s` to have a ' +
|
81
|
+
'valid `%s`. Instead got `%s`.',
|
82
|
+
fragmentNode.name,
|
83
|
+
START_CURSOR,
|
84
|
+
cursor,
|
85
|
+
);
|
86
|
+
|
87
|
+
let hasMore;
|
88
|
+
if (direction === 'forward') {
|
89
|
+
hasMore = cursor != null && pageInfo[HAS_NEXT_PAGE] === true;
|
90
|
+
} else {
|
91
|
+
hasMore = cursor != null && pageInfo[HAS_PREV_PAGE] === true;
|
92
|
+
}
|
93
|
+
|
94
|
+
return {cursor, hasMore};
|
95
|
+
}
|
96
|
+
|
97
|
+
module.exports = getConnectionState;
|
@@ -452,7 +452,7 @@ class FragmentResourceImpl {
|
|
452
452
|
missingLiveResolverFields(snapshot)?.map(({liveStateID}) => {
|
453
453
|
const store = environment.getStore();
|
454
454
|
|
455
|
-
// $FlowFixMe[prop-missing] This is expected to be a
|
455
|
+
// $FlowFixMe[prop-missing] This is expected to be a RelayModernStore
|
456
456
|
return store.getLiveResolverPromise(liveStateID);
|
457
457
|
}) ?? [];
|
458
458
|
|
@@ -559,21 +559,12 @@ class FragmentResourceImpl {
|
|
559
559
|
_throwOrLogErrorsInSnapshot(snapshot: SingularOrPluralSnapshot) {
|
560
560
|
if (Array.isArray(snapshot)) {
|
561
561
|
snapshot.forEach(s => {
|
562
|
-
handlePotentialSnapshotErrors(
|
563
|
-
this._environment,
|
564
|
-
s.missingRequiredFields,
|
565
|
-
s.relayResolverErrors,
|
566
|
-
s.errorResponseFields,
|
567
|
-
s.selector.node.metadata?.throwOnFieldError ?? false,
|
568
|
-
);
|
562
|
+
handlePotentialSnapshotErrors(this._environment, s.errorResponseFields);
|
569
563
|
});
|
570
564
|
} else {
|
571
565
|
handlePotentialSnapshotErrors(
|
572
566
|
this._environment,
|
573
|
-
snapshot.missingRequiredFields,
|
574
|
-
snapshot.relayResolverErrors,
|
575
567
|
snapshot.errorResponseFields,
|
576
|
-
snapshot.selector.node.metadata?.throwOnFieldError ?? false,
|
577
568
|
);
|
578
569
|
}
|
579
570
|
}
|
@@ -773,8 +764,6 @@ class FragmentResourceImpl {
|
|
773
764
|
missingLiveResolverFields: currentSnapshot.missingLiveResolverFields,
|
774
765
|
seenRecords: currentSnapshot.seenRecords,
|
775
766
|
selector: currentSnapshot.selector,
|
776
|
-
missingRequiredFields: currentSnapshot.missingRequiredFields,
|
777
|
-
relayResolverErrors: currentSnapshot.relayResolverErrors,
|
778
767
|
errorResponseFields: currentSnapshot.errorResponseFields,
|
779
768
|
};
|
780
769
|
if (updatedData !== renderData) {
|
@@ -17,13 +17,15 @@ import type {
|
|
17
17
|
EnvironmentProviderOptions,
|
18
18
|
IEnvironmentProvider,
|
19
19
|
PreloadedEntryPoint,
|
20
|
+
PreloadedQuery,
|
20
21
|
} from './EntryPointTypes.flow';
|
21
22
|
|
22
23
|
const {loadQuery} = require('./loadQuery');
|
23
24
|
|
24
25
|
function loadEntryPoint<
|
25
26
|
TEntryPointParams: {...},
|
26
|
-
|
27
|
+
// $FlowExpectedError[unclear-type] Need any to make it supertype of all PreloadedQuery
|
28
|
+
TPreloadedQueries: {+[string]: PreloadedQuery<any>},
|
27
29
|
TPreloadedEntryPoints: {...},
|
28
30
|
TRuntimeProps: {...},
|
29
31
|
TExtraProps,
|
@@ -53,8 +55,12 @@ function loadEntryPoint<
|
|
53
55
|
if (queries != null) {
|
54
56
|
const queriesPropNames = Object.keys(queries);
|
55
57
|
queriesPropNames.forEach(queryPropName => {
|
58
|
+
const query = queries[queryPropName];
|
59
|
+
if (query == null) {
|
60
|
+
return;
|
61
|
+
}
|
56
62
|
const {environmentProviderOptions, options, parameters, variables} =
|
57
|
-
|
63
|
+
query;
|
58
64
|
|
59
65
|
const environment = environmentProvider.getEnvironment(
|
60
66
|
environmentProviderOptions,
|
@@ -86,11 +92,11 @@ function loadEntryPoint<
|
|
86
92
|
entryPointDescription;
|
87
93
|
preloadedEntryPoints[entryPointPropName] = loadEntryPoint<
|
88
94
|
_,
|
89
|
-
{
|
95
|
+
{},
|
90
96
|
{...},
|
91
97
|
{...},
|
92
98
|
mixed,
|
93
|
-
EntryPointComponent<{
|
99
|
+
EntryPointComponent<{}, {...}, {...}, mixed>,
|
94
100
|
_,
|
95
101
|
>(environmentProvider, nestedEntryPoint, nestedParams);
|
96
102
|
});
|
@@ -30,7 +30,6 @@ import type {
|
|
30
30
|
} from 'relay-runtime';
|
31
31
|
|
32
32
|
const invariant = require('invariant');
|
33
|
-
const React = require('react');
|
34
33
|
const {
|
35
34
|
__internal: {fetchQueryDeduped},
|
36
35
|
Observable,
|
@@ -41,30 +40,19 @@ const {
|
|
41
40
|
getRequest,
|
42
41
|
getRequestIdentifier,
|
43
42
|
} = require('relay-runtime');
|
44
|
-
const warning = require('warning');
|
45
43
|
|
46
|
-
let RenderDispatcher = null;
|
47
44
|
let fetchKey = 100001;
|
48
45
|
|
49
|
-
hook useTrackLoadQueryInRender() {
|
50
|
-
if (RenderDispatcher === null) {
|
51
|
-
// Flow does not know of React internals (rightly so), but we need to
|
52
|
-
// ensure here that this function isn't called inside render.
|
53
|
-
RenderDispatcher =
|
54
|
-
// $FlowFixMe[prop-missing]
|
55
|
-
React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
|
56
|
-
?.ReactCurrentDispatcher?.current;
|
57
|
-
}
|
58
|
-
}
|
59
|
-
|
60
46
|
type QueryType<T> =
|
61
47
|
T extends Query<infer V, infer D, infer RR>
|
62
48
|
? {
|
63
49
|
variables: V,
|
64
50
|
response: D,
|
65
51
|
rawResponse?: $NonMaybeType<RR>,
|
66
|
-
}
|
67
|
-
:
|
52
|
+
}
|
53
|
+
: [+t: T] extends [+t: PreloadableConcreteRequest<infer V>]
|
54
|
+
? V
|
55
|
+
: empty;
|
68
56
|
|
69
57
|
declare function loadQuery<
|
70
58
|
T,
|
@@ -87,17 +75,6 @@ function loadQuery<
|
|
87
75
|
options?: ?LoadQueryOptions,
|
88
76
|
environmentProviderOptions?: ?TEnvironmentProviderOptions,
|
89
77
|
): PreloadedQueryInner<TQuery, TEnvironmentProviderOptions> {
|
90
|
-
// This code ensures that we don't call loadQuery during render.
|
91
|
-
const CurrentDispatcher =
|
92
|
-
// $FlowFixMe[prop-missing]
|
93
|
-
React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
|
94
|
-
?.ReactCurrentDispatcher?.current;
|
95
|
-
warning(
|
96
|
-
RenderDispatcher == null || CurrentDispatcher !== RenderDispatcher,
|
97
|
-
'Relay: `%s` should not be called inside a React render function.',
|
98
|
-
options?.__nameForWarning ?? 'loadQuery',
|
99
|
-
);
|
100
|
-
|
101
78
|
// Every time you call loadQuery, we will generate a new fetchKey.
|
102
79
|
// This will ensure that every query reference that is created and
|
103
80
|
// passed to usePreloadedQuery is independently evaluated,
|
@@ -407,5 +384,4 @@ function loadQuery<
|
|
407
384
|
|
408
385
|
module.exports = {
|
409
386
|
loadQuery,
|
410
|
-
useTrackLoadQueryInRender,
|
411
387
|
};
|
@@ -16,13 +16,15 @@ import type {
|
|
16
16
|
EntryPointComponent,
|
17
17
|
EnvironmentProviderOptions,
|
18
18
|
IEnvironmentProvider,
|
19
|
+
PreloadedQuery,
|
19
20
|
} from './EntryPointTypes.flow';
|
20
21
|
|
21
22
|
const preloadQuery = require('./preloadQuery_DEPRECATED');
|
22
23
|
|
23
24
|
function prepareEntryPoint<
|
24
25
|
TEntryPointParams: {...},
|
25
|
-
|
26
|
+
// $FlowExpectedError[unclear-type] Need any to make it supertype of all PreloadedQuery
|
27
|
+
TPreloadedQueries: {+[string]: PreloadedQuery<any>},
|
26
28
|
TPreloadedEntryPoints: {...},
|
27
29
|
TRuntimeProps: {...},
|
28
30
|
TExtraProps,
|
@@ -59,6 +61,7 @@ function prepareEntryPoint<
|
|
59
61
|
environmentProviderOptions,
|
60
62
|
);
|
61
63
|
|
64
|
+
// $FlowFixMe[incompatible-type]
|
62
65
|
preloadedQueries[queryPropName] = preloadQuery<OperationType, mixed>(
|
63
66
|
environment,
|
64
67
|
parameters,
|
@@ -85,20 +85,11 @@ function handlePotentialSnapshotErrorsForState(
|
|
85
85
|
if (state.kind === 'singular') {
|
86
86
|
handlePotentialSnapshotErrors(
|
87
87
|
environment,
|
88
|
-
state.snapshot.missingRequiredFields,
|
89
|
-
state.snapshot.relayResolverErrors,
|
90
88
|
state.snapshot.errorResponseFields,
|
91
|
-
state.snapshot.selector.node.metadata?.throwOnFieldError ?? false,
|
92
89
|
);
|
93
90
|
} else if (state.kind === 'plural') {
|
94
91
|
for (const snapshot of state.snapshots) {
|
95
|
-
handlePotentialSnapshotErrors(
|
96
|
-
environment,
|
97
|
-
snapshot.missingRequiredFields,
|
98
|
-
snapshot.relayResolverErrors,
|
99
|
-
snapshot.errorResponseFields,
|
100
|
-
snapshot.selector.node.metadata?.throwOnFieldError ?? false,
|
101
|
-
);
|
92
|
+
handlePotentialSnapshotErrors(environment, snapshot.errorResponseFields);
|
102
93
|
}
|
103
94
|
}
|
104
95
|
}
|
@@ -17,10 +17,10 @@ import type {
|
|
17
17
|
EnvironmentProviderOptions,
|
18
18
|
IEnvironmentProvider,
|
19
19
|
PreloadedEntryPoint,
|
20
|
+
PreloadedQuery,
|
20
21
|
} from './EntryPointTypes.flow';
|
21
22
|
|
22
23
|
const loadEntryPoint = require('./loadEntryPoint');
|
23
|
-
const {useTrackLoadQueryInRender} = require('./loadQuery');
|
24
24
|
const useIsMountedRef = require('./useIsMountedRef');
|
25
25
|
const {useCallback, useEffect, useRef, useState} = require('react');
|
26
26
|
|
@@ -52,7 +52,8 @@ const initialNullEntryPointReferenceState = {kind: 'NullEntryPointReference'};
|
|
52
52
|
|
53
53
|
hook useLoadEntryPoint<
|
54
54
|
TEntryPointParams: {...},
|
55
|
-
|
55
|
+
// $FlowExpectedError[unclear-type] Need any to make it supertype of all PreloadedQuery
|
56
|
+
TPreloadedQueries: {+[string]: PreloadedQuery<any>},
|
56
57
|
TPreloadedEntryPoints: {...},
|
57
58
|
TRuntimeProps: {...},
|
58
59
|
TExtraProps,
|
@@ -102,8 +103,6 @@ hook useLoadEntryPoint<
|
|
102
103
|
* entry point references.
|
103
104
|
*/
|
104
105
|
|
105
|
-
useTrackLoadQueryInRender();
|
106
|
-
|
107
106
|
const initialEntryPointReferenceInternal =
|
108
107
|
options?.TEST_ONLY__initialEntryPointData?.entryPointReference ??
|
109
108
|
initialNullEntryPointReferenceState;
|
@@ -13,7 +13,6 @@
|
|
13
13
|
|
14
14
|
import type {Fragment, FragmentType, GraphQLTaggedNode} from 'relay-runtime';
|
15
15
|
|
16
|
-
const {useTrackLoadQueryInRender} = require('./loadQuery');
|
17
16
|
const useFragmentInternal = require('./useFragmentInternal');
|
18
17
|
const useStaticFragmentNodeWarning = require('./useStaticFragmentNodeWarning');
|
19
18
|
const {useDebugValue} = require('react');
|
@@ -49,10 +48,6 @@ declare hook useFragment<TFragmentType: FragmentType, TData>(
|
|
49
48
|
): ?TData;
|
50
49
|
|
51
50
|
hook useFragment(fragment: GraphQLTaggedNode, key: mixed): mixed {
|
52
|
-
// We need to use this hook in order to be able to track if
|
53
|
-
// loadQuery was called during render
|
54
|
-
useTrackLoadQueryInRender();
|
55
|
-
|
56
51
|
const fragmentNode = getFragment(fragment);
|
57
52
|
useStaticFragmentNodeWarning(fragmentNode, 'first argument of useFragment()');
|
58
53
|
const data = useFragmentInternal(fragmentNode, key, 'useFragment()');
|