react-relay 18.0.0 → 18.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ReactRelayContext.js +1 -1
- package/ReactRelayFragmentContainer.js.flow +2 -5
- package/buildReactRelayContainer.js.flow +1 -0
- package/hooks.js +1 -1
- package/index.js +1 -1
- package/index.js.flow +3 -0
- package/legacy.js +1 -1
- package/lib/index.js +2 -0
- package/lib/relay-hooks/getConnectionState.js +47 -0
- package/lib/relay-hooks/legacy/FragmentResource.js +3 -8
- package/lib/relay-hooks/loadQuery.js +5 -14
- package/lib/relay-hooks/readFragmentInternal.js +2 -4
- package/lib/relay-hooks/useFragmentInternal.js +1 -1
- package/lib/relay-hooks/useFragmentInternal_CURRENT.js +3 -10
- package/lib/relay-hooks/useFragmentInternal_EXPERIMENTAL.js +6 -28
- package/lib/relay-hooks/useLoadMoreFunction.js +10 -43
- package/lib/relay-hooks/useLoadMoreFunction_EXPERIMENTAL.js +130 -0
- package/lib/relay-hooks/usePrefetchableForwardPaginationFragment_EXPERIMENTAL.js +227 -0
- package/lib/relay-hooks/useQueryLoader.js +8 -0
- package/lib/relay-hooks/useQueryLoader_EXPERIMENTAL.js +120 -0
- package/package.json +2 -2
- 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 +2 -2
- package/relay-hooks/MatchContainer.js.flow +1 -1
- package/relay-hooks/getConnectionState.js.flow +97 -0
- package/relay-hooks/legacy/FragmentResource.js.flow +4 -16
- package/relay-hooks/loadQuery.js.flow +30 -38
- package/relay-hooks/readFragmentInternal.js.flow +1 -10
- package/relay-hooks/useFragmentInternal.js.flow +1 -1
- package/relay-hooks/useFragmentInternal_CURRENT.js.flow +7 -22
- package/relay-hooks/useFragmentInternal_EXPERIMENTAL.js.flow +8 -56
- package/relay-hooks/useLoadMoreFunction.js.flow +14 -80
- package/relay-hooks/useLoadMoreFunction_EXPERIMENTAL.js.flow +280 -0
- package/relay-hooks/usePrefetchableForwardPaginationFragment_EXPERIMENTAL.js.flow +433 -0
- package/relay-hooks/useQueryLoader.js.flow +27 -3
- package/relay-hooks/useQueryLoader_EXPERIMENTAL.js.flow +253 -0
@@ -34,7 +34,6 @@ const {
|
|
34
34
|
__internal: {fetchQueryDeduped},
|
35
35
|
Observable,
|
36
36
|
PreloadableQueryRegistry,
|
37
|
-
RelayFeatureFlags,
|
38
37
|
ReplaySubject,
|
39
38
|
createOperationDescriptor,
|
40
39
|
getRequest,
|
@@ -140,34 +139,29 @@ function loadQuery<
|
|
140
139
|
// `source` observable is returned.
|
141
140
|
didMakeNetworkRequest = true;
|
142
141
|
|
143
|
-
let observable;
|
144
142
|
const subject = new ReplaySubject<GraphQLResponse>();
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
const network = environment.getNetwork();
|
165
|
-
return network.execute(params, variables, networkCacheConfig);
|
166
|
-
});
|
167
|
-
} else {
|
143
|
+
|
144
|
+
// Here, we are calling fetchQueryDeduped at the network layer level,
|
145
|
+
// which ensures that only a single network request is active for a given
|
146
|
+
// (environment, identifier) pair.
|
147
|
+
// Since network requests can be started /before/ we have the query ast
|
148
|
+
// necessary to process the results, we need to dedupe the raw requests
|
149
|
+
// separately from deduping the operation execution; specifically,
|
150
|
+
// if `loadQuery` is called multiple times before the query ast is available,
|
151
|
+
// we still want the network request to be deduped.
|
152
|
+
// - If a duplicate active network request is found, it will return an
|
153
|
+
// Observable that replays the events of the already active request.
|
154
|
+
// - If no duplicate active network request is found, it will call the fetchFn
|
155
|
+
// to start the request, and return an Observable that will replay
|
156
|
+
// the events from the network request.
|
157
|
+
// We provide an extra key to the identifier to distinguish deduping
|
158
|
+
// of raw network requests vs deduping of operation executions.
|
159
|
+
const identifier: RequestIdentifier =
|
160
|
+
'raw-network-request-' + getRequestIdentifier(params, variables);
|
161
|
+
const observable = fetchQueryDeduped(environment, identifier, () => {
|
168
162
|
const network = environment.getNetwork();
|
169
|
-
|
170
|
-
}
|
163
|
+
return network.execute(params, variables, networkCacheConfig);
|
164
|
+
});
|
171
165
|
|
172
166
|
const {unsubscribe} = observable.subscribe({
|
173
167
|
error(err) {
|
@@ -196,17 +190,15 @@ function loadQuery<
|
|
196
190
|
operation: OperationDescriptor,
|
197
191
|
fetchFn: () => Observable<GraphQLResponse>,
|
198
192
|
) => {
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
didMakeNetworkRequest = true;
|
209
|
-
}
|
193
|
+
// N.B. at this point, if we're calling execute with a query ast (OperationDescriptor),
|
194
|
+
// we are guaranteed to have started a network request. We set this to
|
195
|
+
// true here as well since `makeNetworkRequest` might get skipped in the case
|
196
|
+
// where the query ast is already available and the query executions get deduped.
|
197
|
+
// Even if the execution gets deduped below, we still wan't to return
|
198
|
+
// an observable that provides the replayed network events for the query,
|
199
|
+
// so we set this to true before deduping, to guarantee that the `source`
|
200
|
+
// observable is returned.
|
201
|
+
didMakeNetworkRequest = true;
|
210
202
|
|
211
203
|
// Here, we are calling fetchQueryDeduped, which ensures that only
|
212
204
|
// a single operation is active for a given (environment, identifier) pair,
|
@@ -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
|
}
|
@@ -24,7 +24,7 @@ hook useFragmentInternal(
|
|
24
24
|
hookDisplayName: string,
|
25
25
|
queryOptions?: FragmentQueryOptions,
|
26
26
|
): ?SelectorData | Array<?SelectorData> {
|
27
|
-
if (RelayFeatureFlags.
|
27
|
+
if (RelayFeatureFlags.ENABLE_ACTIVITY_COMPATIBILITY) {
|
28
28
|
// $FlowFixMe[react-rule-hook] - the condition is static
|
29
29
|
return useFragmentInternal_EXPERIMENTAL(
|
30
30
|
fragmentNode,
|
@@ -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,10 +22,7 @@ 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');
|
@@ -89,13 +87,13 @@ function getMissingClientEdges(
|
|
89
87
|
|
90
88
|
function getSuspendingLiveResolver(
|
91
89
|
state: FragmentState,
|
92
|
-
): $ReadOnlyArray<
|
90
|
+
): $ReadOnlyArray<DataID> | null {
|
93
91
|
if (state.kind === 'bailout') {
|
94
92
|
return null;
|
95
93
|
} else if (state.kind === 'singular') {
|
96
94
|
return state.snapshot.missingLiveResolverFields ?? null;
|
97
95
|
} else {
|
98
|
-
let missingFields: null | Array<
|
96
|
+
let missingFields: null | Array<DataID> = null;
|
99
97
|
for (const snapshot of state.snapshots) {
|
100
98
|
if (snapshot.missingLiveResolverFields) {
|
101
99
|
missingFields = missingFields ?? [];
|
@@ -115,20 +113,11 @@ function handlePotentialSnapshotErrorsForState(
|
|
115
113
|
if (state.kind === 'singular') {
|
116
114
|
handlePotentialSnapshotErrors(
|
117
115
|
environment,
|
118
|
-
state.snapshot.missingRequiredFields,
|
119
|
-
state.snapshot.relayResolverErrors,
|
120
116
|
state.snapshot.errorResponseFields,
|
121
|
-
state.snapshot.selector.node.metadata?.throwOnFieldError ?? false,
|
122
117
|
);
|
123
118
|
} else if (state.kind === 'plural') {
|
124
119
|
for (const snapshot of state.snapshots) {
|
125
|
-
handlePotentialSnapshotErrors(
|
126
|
-
environment,
|
127
|
-
snapshot.missingRequiredFields,
|
128
|
-
snapshot.relayResolverErrors,
|
129
|
-
snapshot.errorResponseFields,
|
130
|
-
snapshot.selector.node.metadata?.throwOnFieldError ?? false,
|
131
|
-
);
|
120
|
+
handlePotentialSnapshotErrors(environment, snapshot.errorResponseFields);
|
132
121
|
}
|
133
122
|
}
|
134
123
|
}
|
@@ -164,8 +153,6 @@ function handleMissedUpdates(
|
|
164
153
|
missingLiveResolverFields: currentSnapshot.missingLiveResolverFields,
|
165
154
|
seenRecords: currentSnapshot.seenRecords,
|
166
155
|
selector: currentSnapshot.selector,
|
167
|
-
missingRequiredFields: currentSnapshot.missingRequiredFields,
|
168
|
-
relayResolverErrors: currentSnapshot.relayResolverErrors,
|
169
156
|
errorResponseFields: currentSnapshot.errorResponseFields,
|
170
157
|
};
|
171
158
|
return [
|
@@ -190,8 +177,6 @@ function handleMissedUpdates(
|
|
190
177
|
missingLiveResolverFields: currentSnapshot.missingLiveResolverFields,
|
191
178
|
seenRecords: currentSnapshot.seenRecords,
|
192
179
|
selector: currentSnapshot.selector,
|
193
|
-
missingRequiredFields: currentSnapshot.missingRequiredFields,
|
194
|
-
relayResolverErrors: currentSnapshot.relayResolverErrors,
|
195
180
|
errorResponseFields: currentSnapshot.errorResponseFields,
|
196
181
|
};
|
197
182
|
if (updatedData !== snapshot.data) {
|
@@ -521,8 +506,8 @@ hook useFragmentInternal(
|
|
521
506
|
const suspendingLiveResolvers = getSuspendingLiveResolver(state);
|
522
507
|
if (suspendingLiveResolvers != null && suspendingLiveResolvers.length > 0) {
|
523
508
|
throw Promise.all(
|
524
|
-
suspendingLiveResolvers.map(
|
525
|
-
// $FlowFixMe[prop-missing] This is expected to be a
|
509
|
+
suspendingLiveResolvers.map(liveStateID => {
|
510
|
+
// $FlowFixMe[prop-missing] This is expected to be a RelayModernStore
|
526
511
|
return environment.getStore().getLiveResolverPromise(liveStateID);
|
527
512
|
}),
|
528
513
|
);
|
@@ -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,10 +22,7 @@ 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');
|
@@ -101,13 +99,13 @@ function getMissingClientEdges(
|
|
101
99
|
|
102
100
|
function getSuspendingLiveResolver(
|
103
101
|
state: FragmentState,
|
104
|
-
): $ReadOnlyArray<
|
102
|
+
): $ReadOnlyArray<DataID> | null {
|
105
103
|
if (state.kind === 'bailout') {
|
106
104
|
return null;
|
107
105
|
} else if (state.kind === 'singular') {
|
108
106
|
return state.snapshot.missingLiveResolverFields ?? null;
|
109
107
|
} else {
|
110
|
-
let missingFields: null | Array<
|
108
|
+
let missingFields: null | Array<DataID> = null;
|
111
109
|
for (const snapshot of state.snapshots) {
|
112
110
|
if (snapshot.missingLiveResolverFields) {
|
113
111
|
missingFields = missingFields ?? [];
|
@@ -127,20 +125,11 @@ function handlePotentialSnapshotErrorsForState(
|
|
127
125
|
if (state.kind === 'singular') {
|
128
126
|
handlePotentialSnapshotErrors(
|
129
127
|
environment,
|
130
|
-
state.snapshot.missingRequiredFields,
|
131
|
-
state.snapshot.relayResolverErrors,
|
132
128
|
state.snapshot.errorResponseFields,
|
133
|
-
state.snapshot.selector.node.metadata?.throwOnFieldError ?? false,
|
134
129
|
);
|
135
130
|
} else if (state.kind === 'plural') {
|
136
131
|
for (const snapshot of state.snapshots) {
|
137
|
-
handlePotentialSnapshotErrors(
|
138
|
-
environment,
|
139
|
-
snapshot.missingRequiredFields,
|
140
|
-
snapshot.relayResolverErrors,
|
141
|
-
snapshot.errorResponseFields,
|
142
|
-
snapshot.selector.node.metadata?.throwOnFieldError ?? false,
|
143
|
-
);
|
132
|
+
handlePotentialSnapshotErrors(environment, snapshot.errorResponseFields);
|
144
133
|
}
|
145
134
|
}
|
146
135
|
}
|
@@ -176,8 +165,6 @@ function handleMissedUpdates(
|
|
176
165
|
missingLiveResolverFields: currentSnapshot.missingLiveResolverFields,
|
177
166
|
seenRecords: currentSnapshot.seenRecords,
|
178
167
|
selector: currentSnapshot.selector,
|
179
|
-
missingRequiredFields: currentSnapshot.missingRequiredFields,
|
180
|
-
relayResolverErrors: currentSnapshot.relayResolverErrors,
|
181
168
|
errorResponseFields: currentSnapshot.errorResponseFields,
|
182
169
|
};
|
183
170
|
return [
|
@@ -204,8 +191,6 @@ function handleMissedUpdates(
|
|
204
191
|
missingLiveResolverFields: currentSnapshot.missingLiveResolverFields,
|
205
192
|
seenRecords: currentSnapshot.seenRecords,
|
206
193
|
selector: currentSnapshot.selector,
|
207
|
-
missingRequiredFields: currentSnapshot.missingRequiredFields,
|
208
|
-
relayResolverErrors: currentSnapshot.relayResolverErrors,
|
209
194
|
errorResponseFields: currentSnapshot.errorResponseFields,
|
210
195
|
};
|
211
196
|
if (updatedData !== snapshot.data) {
|
@@ -271,7 +256,6 @@ function subscribeToSnapshot(
|
|
271
256
|
environment: IEnvironment,
|
272
257
|
state: FragmentState,
|
273
258
|
setState: StateUpdaterFunction<FragmentState>,
|
274
|
-
pendingStateRef: {current: number | null},
|
275
259
|
): () => void {
|
276
260
|
if (state.kind === 'bailout') {
|
277
261
|
return () => {};
|
@@ -307,8 +291,6 @@ function subscribeToSnapshot(
|
|
307
291
|
environment: state.environment,
|
308
292
|
};
|
309
293
|
}
|
310
|
-
pendingStateRef.current =
|
311
|
-
nextState.kind === 'singular' ? nextState.epoch : null;
|
312
294
|
return nextState;
|
313
295
|
});
|
314
296
|
});
|
@@ -353,8 +335,6 @@ function subscribeToSnapshot(
|
|
353
335
|
environment: state.environment,
|
354
336
|
};
|
355
337
|
}
|
356
|
-
pendingStateRef.current =
|
357
|
-
nextState.kind === 'plural' ? nextState.epoch : null;
|
358
338
|
return nextState;
|
359
339
|
});
|
360
340
|
}),
|
@@ -541,8 +521,8 @@ hook useFragmentInternal_EXPERIMENTAL(
|
|
541
521
|
const suspendingLiveResolvers = getSuspendingLiveResolver(state);
|
542
522
|
if (suspendingLiveResolvers != null && suspendingLiveResolvers.length > 0) {
|
543
523
|
throw Promise.all(
|
544
|
-
suspendingLiveResolvers.map(
|
545
|
-
// $FlowFixMe[prop-missing] This is expected to be a
|
524
|
+
suspendingLiveResolvers.map(liveStateID => {
|
525
|
+
// $FlowFixMe[prop-missing] This is expected to be a RelayModernStore
|
546
526
|
return environment.getStore().getLiveResolverPromise(liveStateID);
|
547
527
|
}),
|
548
528
|
);
|
@@ -578,11 +558,6 @@ hook useFragmentInternal_EXPERIMENTAL(
|
|
578
558
|
// they're missing even though we are out of options for possibly fetching them:
|
579
559
|
handlePotentialSnapshotErrorsForState(environment, state);
|
580
560
|
|
581
|
-
// Ref that stores the epoch of the pending setState, if any. This is used to check
|
582
|
-
// if the state we're rendering is at least as current as the pending update, and
|
583
|
-
// force a refresh if stale.
|
584
|
-
const pendingStateEpochRef = useRef<number | null>(null);
|
585
|
-
|
586
561
|
// We emulate CRUD effects using a ref and two effects:
|
587
562
|
// - The ref tracks the current state (including updates from the subscription)
|
588
563
|
// and the dispose function for the current subscription. This is null until
|
@@ -647,7 +622,6 @@ hook useFragmentInternal_EXPERIMENTAL(
|
|
647
622
|
state.environment,
|
648
623
|
stateForSubscription,
|
649
624
|
setState,
|
650
|
-
pendingStateEpochRef,
|
651
625
|
);
|
652
626
|
storeSubscriptionRef.current = {
|
653
627
|
dispose,
|
@@ -657,12 +631,7 @@ hook useFragmentInternal_EXPERIMENTAL(
|
|
657
631
|
}, [state]);
|
658
632
|
useEffect(() => {
|
659
633
|
if (storeSubscriptionRef.current == null && state.kind !== 'bailout') {
|
660
|
-
const dispose = subscribeToSnapshot(
|
661
|
-
state.environment,
|
662
|
-
state,
|
663
|
-
setState,
|
664
|
-
pendingStateEpochRef,
|
665
|
-
);
|
634
|
+
const dispose = subscribeToSnapshot(state.environment, state, setState);
|
666
635
|
storeSubscriptionRef.current = {
|
667
636
|
dispose,
|
668
637
|
selector: state.selector,
|
@@ -677,23 +646,6 @@ hook useFragmentInternal_EXPERIMENTAL(
|
|
677
646
|
// simulating a CRUD effect
|
678
647
|
}, []);
|
679
648
|
|
680
|
-
// If a low-priority update was queued and hasn't rendered yet, render it now
|
681
|
-
if (
|
682
|
-
pendingStateEpochRef.current !== null &&
|
683
|
-
pendingStateEpochRef.current !== state.epoch
|
684
|
-
) {
|
685
|
-
const updates = handleMissedUpdates(environment, state);
|
686
|
-
if (updates != null) {
|
687
|
-
const [hasStateUpdates, updatedState] = updates;
|
688
|
-
if (hasStateUpdates) {
|
689
|
-
setState(updatedState);
|
690
|
-
state = updatedState;
|
691
|
-
}
|
692
|
-
}
|
693
|
-
}
|
694
|
-
// $FlowFixMe[react-rule-unsafe-ref]
|
695
|
-
pendingStateEpochRef.current = null;
|
696
|
-
|
697
649
|
let data: ?SelectorData | Array<?SelectorData>;
|
698
650
|
if (isPlural) {
|
699
651
|
// Plural fragments require allocating an array of the snapshot data values,
|
@@ -22,20 +22,21 @@ import type {
|
|
22
22
|
Variables,
|
23
23
|
} from 'relay-runtime';
|
24
24
|
|
25
|
+
const getConnectionState = require('./getConnectionState');
|
25
26
|
const useFetchTrackingRef = require('./useFetchTrackingRef');
|
26
27
|
const useIsMountedRef = require('./useIsMountedRef');
|
27
28
|
const useIsOperationNodeActive = require('./useIsOperationNodeActive');
|
29
|
+
const useLoadMoreFunction_EXPERIMENTAL = require('./useLoadMoreFunction_EXPERIMENTAL');
|
28
30
|
const useRelayEnvironment = require('./useRelayEnvironment');
|
29
31
|
const invariant = require('invariant');
|
30
32
|
const {useCallback, useEffect, useState} = require('react');
|
31
33
|
const {
|
32
34
|
__internal: {fetchQuery},
|
33
|
-
|
35
|
+
RelayFeatureFlags,
|
34
36
|
createOperationDescriptor,
|
35
37
|
getPaginationVariables,
|
36
38
|
getRefetchMetadata,
|
37
39
|
getSelector,
|
38
|
-
getValueAtPath,
|
39
40
|
} = require('relay-runtime');
|
40
41
|
const warning = require('warning');
|
41
42
|
|
@@ -63,6 +64,17 @@ export type UseLoadMoreFunctionArgs = {
|
|
63
64
|
|
64
65
|
hook useLoadMoreFunction<TVariables: Variables>(
|
65
66
|
args: UseLoadMoreFunctionArgs,
|
67
|
+
): [LoadMoreFn<TVariables>, boolean, () => void] {
|
68
|
+
if (RelayFeatureFlags.ENABLE_ACTIVITY_COMPATIBILITY) {
|
69
|
+
// $FlowFixMe[react-rule-hook] - the condition is static
|
70
|
+
return useLoadMoreFunction_EXPERIMENTAL(args);
|
71
|
+
}
|
72
|
+
// $FlowFixMe[react-rule-hook] - the condition is static
|
73
|
+
return useLoadMoreFunction_CURRENT(args);
|
74
|
+
}
|
75
|
+
|
76
|
+
hook useLoadMoreFunction_CURRENT<TVariables: Variables>(
|
77
|
+
args: UseLoadMoreFunctionArgs,
|
66
78
|
): [LoadMoreFn<TVariables>, boolean, () => void] {
|
67
79
|
const {
|
68
80
|
direction,
|
@@ -269,82 +281,4 @@ hook useLoadMoreFunction<TVariables: Variables>(
|
|
269
281
|
return [loadMore, hasMore, disposeFetch];
|
270
282
|
}
|
271
283
|
|
272
|
-
function getConnectionState(
|
273
|
-
direction: Direction,
|
274
|
-
fragmentNode: ReaderFragment,
|
275
|
-
fragmentData: mixed,
|
276
|
-
connectionPathInFragmentData: $ReadOnlyArray<string | number>,
|
277
|
-
): {
|
278
|
-
cursor: ?string,
|
279
|
-
hasMore: boolean,
|
280
|
-
} {
|
281
|
-
const {
|
282
|
-
EDGES,
|
283
|
-
PAGE_INFO,
|
284
|
-
HAS_NEXT_PAGE,
|
285
|
-
HAS_PREV_PAGE,
|
286
|
-
END_CURSOR,
|
287
|
-
START_CURSOR,
|
288
|
-
} = ConnectionInterface.get();
|
289
|
-
const connection = getValueAtPath(fragmentData, connectionPathInFragmentData);
|
290
|
-
if (connection == null) {
|
291
|
-
return {cursor: null, hasMore: false};
|
292
|
-
}
|
293
|
-
|
294
|
-
invariant(
|
295
|
-
typeof connection === 'object',
|
296
|
-
'Relay: Expected connection in fragment `%s` to have been `null`, or ' +
|
297
|
-
'a plain object with %s and %s properties. Instead got `%s`.',
|
298
|
-
fragmentNode.name,
|
299
|
-
EDGES,
|
300
|
-
PAGE_INFO,
|
301
|
-
connection,
|
302
|
-
);
|
303
|
-
|
304
|
-
const edges = connection[EDGES];
|
305
|
-
const pageInfo = connection[PAGE_INFO];
|
306
|
-
if (edges == null || pageInfo == null) {
|
307
|
-
return {cursor: null, hasMore: false};
|
308
|
-
}
|
309
|
-
|
310
|
-
invariant(
|
311
|
-
Array.isArray(edges),
|
312
|
-
'Relay: Expected connection in fragment `%s` to have a plural `%s` field. ' +
|
313
|
-
'Instead got `%s`.',
|
314
|
-
fragmentNode.name,
|
315
|
-
EDGES,
|
316
|
-
edges,
|
317
|
-
);
|
318
|
-
invariant(
|
319
|
-
typeof pageInfo === 'object',
|
320
|
-
'Relay: Expected connection in fragment `%s` to have a `%s` field. ' +
|
321
|
-
'Instead got `%s`.',
|
322
|
-
fragmentNode.name,
|
323
|
-
PAGE_INFO,
|
324
|
-
pageInfo,
|
325
|
-
);
|
326
|
-
|
327
|
-
const cursor =
|
328
|
-
direction === 'forward'
|
329
|
-
? pageInfo[END_CURSOR] ?? null
|
330
|
-
: pageInfo[START_CURSOR] ?? null;
|
331
|
-
invariant(
|
332
|
-
cursor === null || typeof cursor === 'string',
|
333
|
-
'Relay: Expected page info for connection in fragment `%s` to have a ' +
|
334
|
-
'valid `%s`. Instead got `%s`.',
|
335
|
-
fragmentNode.name,
|
336
|
-
START_CURSOR,
|
337
|
-
cursor,
|
338
|
-
);
|
339
|
-
|
340
|
-
let hasMore;
|
341
|
-
if (direction === 'forward') {
|
342
|
-
hasMore = cursor != null && pageInfo[HAS_NEXT_PAGE] === true;
|
343
|
-
} else {
|
344
|
-
hasMore = cursor != null && pageInfo[HAS_PREV_PAGE] === true;
|
345
|
-
}
|
346
|
-
|
347
|
-
return {cursor, hasMore};
|
348
|
-
}
|
349
|
-
|
350
284
|
module.exports = useLoadMoreFunction;
|