react-relay 18.1.0 → 19.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/ReactRelayContainerUtils.js.flow +2 -2
- package/ReactRelayContext.js +1 -1
- package/ReactRelayFragmentContainer.js.flow +5 -10
- package/ReactRelayLoggingContext.js.flow +21 -0
- package/ReactRelayPaginationContainer.js.flow +8 -8
- package/ReactRelayRefetchContainer.js.flow +8 -8
- package/ReactRelayTypes.js.flow +18 -11
- package/__flowtests__/ReactRelayFragmentContainer-flowtest.js.flow +1 -8
- package/__flowtests__/ReactRelayPaginationContainer-flowtest.js.flow +2 -5
- package/__flowtests__/ReactRelayRefetchContainer-flowtest.js.flow +2 -5
- package/buildReactRelayContainer.js.flow +3 -3
- package/hooks.js +1 -1
- package/index.js +1 -1
- package/index.js.flow +3 -0
- package/legacy.js +1 -1
- package/lib/ReactRelayLoggingContext.js +6 -0
- package/lib/index.js +2 -0
- package/lib/relay-hooks/legacy/FragmentResource.js +4 -5
- package/lib/relay-hooks/legacy/useRefetchableFragmentNode.js +1 -1
- package/lib/relay-hooks/loadEntryPoint.js +3 -0
- package/lib/relay-hooks/loadQuery.js +9 -16
- package/lib/relay-hooks/preloadQuery_DEPRECATED.js +7 -2
- package/lib/relay-hooks/readFragmentInternal.js +2 -2
- package/lib/relay-hooks/useFragmentInternal_CURRENT.js +12 -8
- package/lib/relay-hooks/useFragmentInternal_EXPERIMENTAL.js +12 -8
- package/lib/relay-hooks/useLoadMoreFunction.js +3 -2
- package/lib/relay-hooks/useLoadMoreFunction_EXPERIMENTAL.js +3 -2
- package/lib/relay-hooks/usePaginationFragment.js +5 -1
- package/lib/relay-hooks/usePrefetchableForwardPaginationFragment.js +228 -0
- package/lib/relay-hooks/usePrefetchableForwardPaginationFragment_EXPERIMENTAL.js +227 -0
- package/lib/relay-hooks/useRefetchableFragmentInternal.js +3 -3
- package/lib/relay-hooks/useRelayLoggingContext.js +9 -0
- package/package.json +3 -3
- package/relay-hooks/EntryPointContainer.react.js.flow +13 -17
- package/relay-hooks/EntryPointTypes.flow.js.flow +7 -5
- package/relay-hooks/MatchContainer.js.flow +1 -1
- package/relay-hooks/legacy/FragmentResource.js.flow +5 -9
- package/relay-hooks/legacy/useBlockingPaginationFragment.js.flow +2 -17
- package/relay-hooks/legacy/useRefetchableFragmentNode.js.flow +1 -1
- package/relay-hooks/loadEntryPoint.js.flow +6 -0
- package/relay-hooks/loadQuery.js.flow +47 -39
- package/relay-hooks/preloadQuery_DEPRECATED.js.flow +18 -3
- package/relay-hooks/readFragmentInternal.js.flow +2 -5
- package/relay-hooks/useEntryPointLoader.js.flow +4 -2
- package/relay-hooks/useFragment.js.flow +1 -0
- package/relay-hooks/useFragmentInternal.js.flow +2 -0
- package/relay-hooks/useFragmentInternal_CURRENT.js.flow +27 -12
- package/relay-hooks/useFragmentInternal_EXPERIMENTAL.js.flow +29 -12
- package/relay-hooks/useLazyLoadQuery.js.flow +4 -4
- package/relay-hooks/useLoadMoreFunction.js.flow +7 -7
- package/relay-hooks/useLoadMoreFunction_EXPERIMENTAL.js.flow +5 -7
- package/relay-hooks/usePaginationFragment.js.flow +6 -10
- package/relay-hooks/usePrefetchableForwardPaginationFragment.js.flow +436 -0
- package/relay-hooks/usePrefetchableForwardPaginationFragment_EXPERIMENTAL.js.flow +435 -0
- package/relay-hooks/usePreloadedQuery.js.flow +1 -0
- package/relay-hooks/useQueryLoader.js.flow +5 -1
- package/relay-hooks/useQueryLoader_EXPERIMENTAL.js.flow +3 -1
- package/relay-hooks/useRefetchableFragment.js.flow +1 -0
- package/relay-hooks/useRefetchableFragmentInternal.js.flow +3 -3
- package/relay-hooks/useRelayLoggingContext.js.flow +21 -0
- package/relay-hooks/useStaticFragmentNodeWarning.js.flow +1 -0
- package/react-relay-hooks.js +0 -4
- package/react-relay-hooks.min.js +0 -9
- package/react-relay-legacy.js +0 -4
- package/react-relay-legacy.min.js +0 -9
- package/react-relay.js +0 -4
- package/react-relay.min.js +0 -9
@@ -14,6 +14,7 @@
|
|
14
14
|
import type {QueryResult} from './QueryResource';
|
15
15
|
import type {
|
16
16
|
CacheConfig,
|
17
|
+
DataID,
|
17
18
|
FetchPolicy,
|
18
19
|
IEnvironment,
|
19
20
|
ReaderFragment,
|
@@ -21,13 +22,11 @@ import type {
|
|
21
22
|
SelectorData,
|
22
23
|
Snapshot,
|
23
24
|
} from 'relay-runtime';
|
24
|
-
import type {
|
25
|
-
MissingClientEdgeRequestInfo,
|
26
|
-
MissingLiveResolverField,
|
27
|
-
} from 'relay-runtime/store/RelayStoreTypes';
|
25
|
+
import type {MissingClientEdgeRequestInfo} from 'relay-runtime/store/RelayStoreTypes';
|
28
26
|
|
29
27
|
const {getQueryResourceForEnvironment} = require('./QueryResource');
|
30
28
|
const useRelayEnvironment = require('./useRelayEnvironment');
|
29
|
+
const useRelayLoggingContext = require('./useRelayLoggingContext');
|
31
30
|
const invariant = require('invariant');
|
32
31
|
const {useDebugValue, useEffect, useMemo, useRef, useState} = require('react');
|
33
32
|
const {
|
@@ -101,13 +100,13 @@ function getMissingClientEdges(
|
|
101
100
|
|
102
101
|
function getSuspendingLiveResolver(
|
103
102
|
state: FragmentState,
|
104
|
-
): $ReadOnlyArray<
|
103
|
+
): $ReadOnlyArray<DataID> | null {
|
105
104
|
if (state.kind === 'bailout') {
|
106
105
|
return null;
|
107
106
|
} else if (state.kind === 'singular') {
|
108
107
|
return state.snapshot.missingLiveResolverFields ?? null;
|
109
108
|
} else {
|
110
|
-
let missingFields: null | Array<
|
109
|
+
let missingFields: null | Array<DataID> = null;
|
111
110
|
for (const snapshot of state.snapshots) {
|
112
111
|
if (snapshot.missingLiveResolverFields) {
|
113
112
|
missingFields = missingFields ?? [];
|
@@ -123,15 +122,21 @@ function getSuspendingLiveResolver(
|
|
123
122
|
function handlePotentialSnapshotErrorsForState(
|
124
123
|
environment: IEnvironment,
|
125
124
|
state: FragmentState,
|
125
|
+
loggingContext: mixed | void,
|
126
126
|
): void {
|
127
127
|
if (state.kind === 'singular') {
|
128
128
|
handlePotentialSnapshotErrors(
|
129
129
|
environment,
|
130
|
-
state.snapshot.
|
130
|
+
state.snapshot.fieldErrors,
|
131
|
+
loggingContext,
|
131
132
|
);
|
132
133
|
} else if (state.kind === 'plural') {
|
133
134
|
for (const snapshot of state.snapshots) {
|
134
|
-
handlePotentialSnapshotErrors(
|
135
|
+
handlePotentialSnapshotErrors(
|
136
|
+
environment,
|
137
|
+
snapshot.fieldErrors,
|
138
|
+
loggingContext,
|
139
|
+
);
|
135
140
|
}
|
136
141
|
}
|
137
142
|
}
|
@@ -167,7 +172,7 @@ function handleMissedUpdates(
|
|
167
172
|
missingLiveResolverFields: currentSnapshot.missingLiveResolverFields,
|
168
173
|
seenRecords: currentSnapshot.seenRecords,
|
169
174
|
selector: currentSnapshot.selector,
|
170
|
-
|
175
|
+
fieldErrors: currentSnapshot.fieldErrors,
|
171
176
|
};
|
172
177
|
return [
|
173
178
|
updatedData !== state.snapshot.data,
|
@@ -193,7 +198,7 @@ function handleMissedUpdates(
|
|
193
198
|
missingLiveResolverFields: currentSnapshot.missingLiveResolverFields,
|
194
199
|
seenRecords: currentSnapshot.seenRecords,
|
195
200
|
selector: currentSnapshot.selector,
|
196
|
-
|
201
|
+
fieldErrors: currentSnapshot.fieldErrors,
|
197
202
|
};
|
198
203
|
if (updatedData !== snapshot.data) {
|
199
204
|
didMissUpdates = true;
|
@@ -433,6 +438,12 @@ hook useFragmentInternal_EXPERIMENTAL(
|
|
433
438
|
);
|
434
439
|
|
435
440
|
const environment = useRelayEnvironment();
|
441
|
+
let loggerContext;
|
442
|
+
if (RelayFeatureFlags.ENABLE_UI_CONTEXT_ON_RELAY_LOGGER) {
|
443
|
+
// $FlowFixMe[react-rule-hook] - the condition is static
|
444
|
+
// $FlowFixMe[react-rule-hook-conditional]
|
445
|
+
loggerContext = useRelayLoggingContext();
|
446
|
+
}
|
436
447
|
const [_state, setState] = useState<FragmentState>(() =>
|
437
448
|
getFragmentState(environment, fragmentSelector),
|
438
449
|
);
|
@@ -471,6 +482,7 @@ hook useFragmentInternal_EXPERIMENTAL(
|
|
471
482
|
// always or never run for a given invocation of this hook.
|
472
483
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
473
484
|
// $FlowFixMe[react-rule-hook]
|
485
|
+
// $FlowFixMe[react-rule-hook-conditional]
|
474
486
|
const [clientEdgeQueries, activeRequestPromises] = useMemo(() => {
|
475
487
|
const missingClientEdges = getMissingClientEdges(state);
|
476
488
|
// eslint-disable-next-line no-shadow
|
@@ -502,6 +514,7 @@ hook useFragmentInternal_EXPERIMENTAL(
|
|
502
514
|
// See above note
|
503
515
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
504
516
|
// $FlowFixMe[react-rule-hook]
|
517
|
+
// $FlowFixMe[react-rule-hook-conditional]
|
505
518
|
useEffect(() => {
|
506
519
|
const QueryResource = getQueryResourceForEnvironment(environment);
|
507
520
|
if (clientEdgeQueries?.length) {
|
@@ -523,7 +536,7 @@ hook useFragmentInternal_EXPERIMENTAL(
|
|
523
536
|
const suspendingLiveResolvers = getSuspendingLiveResolver(state);
|
524
537
|
if (suspendingLiveResolvers != null && suspendingLiveResolvers.length > 0) {
|
525
538
|
throw Promise.all(
|
526
|
-
suspendingLiveResolvers.map(
|
539
|
+
suspendingLiveResolvers.map(liveStateID => {
|
527
540
|
// $FlowFixMe[prop-missing] This is expected to be a RelayModernStore
|
528
541
|
return environment.getStore().getLiveResolverPromise(liveStateID);
|
529
542
|
}),
|
@@ -558,7 +571,7 @@ hook useFragmentInternal_EXPERIMENTAL(
|
|
558
571
|
|
559
572
|
// Report required fields only if we're not suspending, since that means
|
560
573
|
// they're missing even though we are out of options for possibly fetching them:
|
561
|
-
handlePotentialSnapshotErrorsForState(environment, state);
|
574
|
+
handlePotentialSnapshotErrorsForState(environment, state, loggerContext);
|
562
575
|
|
563
576
|
// We emulate CRUD effects using a ref and two effects:
|
564
577
|
// - The ref tracks the current state (including updates from the subscription)
|
@@ -579,6 +592,7 @@ hook useFragmentInternal_EXPERIMENTAL(
|
|
579
592
|
selector: ?ReaderSelector,
|
580
593
|
environment: IEnvironment,
|
581
594
|
} | null>(null);
|
595
|
+
// $FlowFixMe[react-rule-hook] - the condition is static
|
582
596
|
useEffect(() => {
|
583
597
|
const storeSubscription = storeSubscriptionRef.current;
|
584
598
|
if (storeSubscription != null) {
|
@@ -631,6 +645,7 @@ hook useFragmentInternal_EXPERIMENTAL(
|
|
631
645
|
environment: state.environment,
|
632
646
|
};
|
633
647
|
}, [state]);
|
648
|
+
// $FlowFixMe[react-rule-hook] - the condition is static
|
634
649
|
useEffect(() => {
|
635
650
|
if (storeSubscriptionRef.current == null && state.kind !== 'bailout') {
|
636
651
|
const dispose = subscribeToSnapshot(state.environment, state, setState);
|
@@ -658,6 +673,7 @@ hook useFragmentInternal_EXPERIMENTAL(
|
|
658
673
|
const fragmentRefIsNullish = fragmentRef == null; // for less sensitive memoization
|
659
674
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
660
675
|
// $FlowFixMe[react-rule-hook]
|
676
|
+
// $FlowFixMe[react-rule-hook-conditional]
|
661
677
|
data = useMemo(() => {
|
662
678
|
if (state.kind === 'bailout') {
|
663
679
|
// Bailout state can happen if the fragmentRef is a plural array that is empty or has no
|
@@ -709,6 +725,7 @@ hook useFragmentInternal_EXPERIMENTAL(
|
|
709
725
|
if (__DEV__) {
|
710
726
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
711
727
|
// $FlowFixMe[react-rule-hook]
|
728
|
+
// $FlowFixMe[react-rule-hook-conditional]
|
712
729
|
useDebugValue({fragment: fragmentNode.name, data});
|
713
730
|
}
|
714
731
|
|
@@ -32,23 +32,23 @@ const {
|
|
32
32
|
export type UseLazyLoadQueryHookType = hook <TVariables: Variables, TData>(
|
33
33
|
gqlQuery: Query<TVariables, TData>,
|
34
34
|
variables: TVariables,
|
35
|
-
options?: {
|
35
|
+
options?: $ReadOnly<{
|
36
36
|
fetchKey?: string | number,
|
37
37
|
fetchPolicy?: FetchPolicy,
|
38
38
|
networkCacheConfig?: CacheConfig,
|
39
39
|
UNSTABLE_renderPolicy?: RenderPolicy,
|
40
|
-
}
|
40
|
+
}>,
|
41
41
|
) => TData;
|
42
42
|
|
43
43
|
hook useLazyLoadQuery<TVariables: Variables, TData>(
|
44
44
|
gqlQuery: Query<TVariables, TData>,
|
45
45
|
variables: TVariables,
|
46
|
-
options?: {
|
46
|
+
options?: $ReadOnly<{
|
47
47
|
fetchKey?: string | number,
|
48
48
|
fetchPolicy?: FetchPolicy,
|
49
49
|
networkCacheConfig?: CacheConfig,
|
50
50
|
UNSTABLE_renderPolicy?: RenderPolicy,
|
51
|
-
}
|
51
|
+
}>,
|
52
52
|
): TData {
|
53
53
|
const environment = useRelayEnvironment();
|
54
54
|
|
@@ -67,9 +67,11 @@ hook useLoadMoreFunction<TVariables: Variables>(
|
|
67
67
|
): [LoadMoreFn<TVariables>, boolean, () => void] {
|
68
68
|
if (RelayFeatureFlags.ENABLE_ACTIVITY_COMPATIBILITY) {
|
69
69
|
// $FlowFixMe[react-rule-hook] - the condition is static
|
70
|
+
// $FlowFixMe[react-rule-hook-conditional]
|
70
71
|
return useLoadMoreFunction_EXPERIMENTAL(args);
|
71
72
|
}
|
72
73
|
// $FlowFixMe[react-rule-hook] - the condition is static
|
74
|
+
// $FlowFixMe[react-rule-hook-conditional]
|
73
75
|
return useLoadMoreFunction_CURRENT(args);
|
74
76
|
}
|
75
77
|
|
@@ -138,6 +140,8 @@ hook useLoadMoreFunction_CURRENT<TVariables: Variables>(
|
|
138
140
|
};
|
139
141
|
}, [disposeFetch]);
|
140
142
|
|
143
|
+
const isRequestInvalid = fragmentData == null || isParentQueryActive;
|
144
|
+
|
141
145
|
const loadMore = useCallback(
|
142
146
|
(
|
143
147
|
count: number,
|
@@ -166,11 +170,8 @@ hook useLoadMoreFunction_CURRENT<TVariables: Variables>(
|
|
166
170
|
}
|
167
171
|
|
168
172
|
const fragmentSelector = getSelector(fragmentNode, fragmentRef);
|
169
|
-
|
170
|
-
|
171
|
-
fragmentData == null ||
|
172
|
-
isParentQueryActive
|
173
|
-
) {
|
173
|
+
|
174
|
+
if (isFetchingRef.current === true || isRequestInvalid) {
|
174
175
|
if (fragmentSelector == null) {
|
175
176
|
warning(
|
176
177
|
false,
|
@@ -271,8 +272,7 @@ hook useLoadMoreFunction_CURRENT<TVariables: Variables>(
|
|
271
272
|
disposeFetch,
|
272
273
|
completeFetch,
|
273
274
|
isFetchingRef,
|
274
|
-
|
275
|
-
fragmentData,
|
275
|
+
isRequestInvalid,
|
276
276
|
fragmentNode.name,
|
277
277
|
fragmentRef,
|
278
278
|
componentDisplayName,
|
@@ -135,6 +135,8 @@ hook useLoadMoreFunction_EXPERIMENTAL<TVariables: Variables>(
|
|
135
135
|
connectionPathInFragmentData,
|
136
136
|
);
|
137
137
|
|
138
|
+
const isRequestInvalid = fragmentData == null || isParentQueryActive;
|
139
|
+
|
138
140
|
const isMountedRef = useIsMountedRef();
|
139
141
|
const loadMore = useCallback(
|
140
142
|
(
|
@@ -164,11 +166,8 @@ hook useLoadMoreFunction_EXPERIMENTAL<TVariables: Variables>(
|
|
164
166
|
}
|
165
167
|
|
166
168
|
const fragmentSelector = getSelector(fragmentNode, fragmentRef);
|
167
|
-
|
168
|
-
|
169
|
-
fragmentData == null ||
|
170
|
-
isParentQueryActive
|
171
|
-
) {
|
169
|
+
|
170
|
+
if (fetchStatusRef.current.kind === 'fetching' || isRequestInvalid) {
|
172
171
|
if (fragmentSelector == null) {
|
173
172
|
warning(
|
174
173
|
false,
|
@@ -267,8 +266,7 @@ hook useLoadMoreFunction_EXPERIMENTAL<TVariables: Variables>(
|
|
267
266
|
identifierValue,
|
268
267
|
direction,
|
269
268
|
cursor,
|
270
|
-
|
271
|
-
fragmentData,
|
269
|
+
isRequestInvalid,
|
272
270
|
fragmentNode.name,
|
273
271
|
fragmentRef,
|
274
272
|
componentDisplayName,
|
@@ -16,8 +16,6 @@ import type {Options} from './useRefetchableFragmentInternal';
|
|
16
16
|
import type {
|
17
17
|
Disposable,
|
18
18
|
FragmentType,
|
19
|
-
GraphQLResponse,
|
20
|
-
Observer,
|
21
19
|
RefetchableFragment,
|
22
20
|
Variables,
|
23
21
|
} from 'relay-runtime';
|
@@ -28,6 +26,7 @@ const useRelayEnvironment = require('./useRelayEnvironment');
|
|
28
26
|
const useStaticFragmentNodeWarning = require('./useStaticFragmentNodeWarning');
|
29
27
|
const {useCallback, useDebugValue, useState} = require('react');
|
30
28
|
const {
|
29
|
+
RelayFeatureFlags,
|
31
30
|
getFragment,
|
32
31
|
getFragmentIdentifier,
|
33
32
|
getPaginationMetadata,
|
@@ -145,6 +144,7 @@ hook usePaginationFragment<
|
|
145
144
|
if (__DEV__) {
|
146
145
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
147
146
|
// $FlowFixMe[react-rule-hook]
|
147
|
+
// $FlowFixMe[react-rule-hook-conditional]
|
148
148
|
useDebugValue({
|
149
149
|
fragment: fragmentNode.name,
|
150
150
|
data: fragmentData,
|
@@ -168,14 +168,7 @@ hook usePaginationFragment<
|
|
168
168
|
}
|
169
169
|
|
170
170
|
hook useLoadMore<TVariables: Variables>(
|
171
|
-
args:
|
172
|
-
UseLoadMoreFunctionArgs,
|
173
|
-
{
|
174
|
-
observer: Observer<GraphQLResponse>,
|
175
|
-
onReset: () => void,
|
176
|
-
...
|
177
|
-
},
|
178
|
-
>,
|
171
|
+
args: Omit<UseLoadMoreFunctionArgs, 'observer' | 'onReset'>,
|
179
172
|
): [LoadMoreFn<TVariables>, boolean, boolean, () => void] {
|
180
173
|
const environment = useRelayEnvironment();
|
181
174
|
const [isLoadingMore, reallySetIsLoadingMore] = useState(false);
|
@@ -196,6 +189,9 @@ hook useLoadMore<TVariables: Variables>(
|
|
196
189
|
start: () => setIsLoadingMore(true),
|
197
190
|
complete: () => setIsLoadingMore(false),
|
198
191
|
error: () => setIsLoadingMore(false),
|
192
|
+
unsubscribe: RelayFeatureFlags.ENABLE_USE_PAGINATION_IS_LOADING_FIX
|
193
|
+
? () => setIsLoadingMore(false)
|
194
|
+
: undefined,
|
199
195
|
};
|
200
196
|
const handleReset = () => setIsLoadingMore(false);
|
201
197
|
const [loadMore, hasMore, disposeFetch] = useLoadMoreFunction<TVariables>({
|