react-relay 18.1.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/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/legacy/FragmentResource.js +1 -2
- package/lib/relay-hooks/loadQuery.js +5 -14
- package/lib/relay-hooks/useFragmentInternal_CURRENT.js +1 -2
- package/lib/relay-hooks/useFragmentInternal_EXPERIMENTAL.js +1 -2
- package/lib/relay-hooks/usePrefetchableForwardPaginationFragment_EXPERIMENTAL.js +227 -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/legacy/FragmentResource.js.flow +2 -3
- package/relay-hooks/loadQuery.js.flow +30 -38
- package/relay-hooks/useFragmentInternal_CURRENT.js.flow +5 -7
- package/relay-hooks/useFragmentInternal_EXPERIMENTAL.js.flow +5 -7
- package/relay-hooks/usePrefetchableForwardPaginationFragment_EXPERIMENTAL.js.flow +433 -0
@@ -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 ?? [];
|
@@ -523,7 +521,7 @@ hook useFragmentInternal_EXPERIMENTAL(
|
|
523
521
|
const suspendingLiveResolvers = getSuspendingLiveResolver(state);
|
524
522
|
if (suspendingLiveResolvers != null && suspendingLiveResolvers.length > 0) {
|
525
523
|
throw Promise.all(
|
526
|
-
suspendingLiveResolvers.map(
|
524
|
+
suspendingLiveResolvers.map(liveStateID => {
|
527
525
|
// $FlowFixMe[prop-missing] This is expected to be a RelayModernStore
|
528
526
|
return environment.getStore().getLiveResolverPromise(liveStateID);
|
529
527
|
}),
|
@@ -0,0 +1,433 @@
|
|
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 {RefetchFn} from './useRefetchableFragment';
|
15
|
+
import type {Options} from './useRefetchableFragmentInternal';
|
16
|
+
import type {FragmentType, Variables} from 'relay-runtime';
|
17
|
+
import type {PrefetchableRefetchableFragment} from 'relay-runtime';
|
18
|
+
|
19
|
+
const useFragment = require('./useFragment');
|
20
|
+
const useLoadMoreFunction = require('./useLoadMoreFunction');
|
21
|
+
const useRefetchableFragmentInternal = require('./useRefetchableFragmentInternal');
|
22
|
+
const useRelayEnvironment = require('./useRelayEnvironment');
|
23
|
+
const useStaticFragmentNodeWarning = require('./useStaticFragmentNodeWarning');
|
24
|
+
const invariant = require('invariant');
|
25
|
+
const {
|
26
|
+
useCallback,
|
27
|
+
useDebugValue,
|
28
|
+
useEffect,
|
29
|
+
useLayoutEffect,
|
30
|
+
useMemo,
|
31
|
+
useRef,
|
32
|
+
useState,
|
33
|
+
} = require('react');
|
34
|
+
const {
|
35
|
+
getFragment,
|
36
|
+
getFragmentIdentifier,
|
37
|
+
getPaginationMetadata,
|
38
|
+
} = require('relay-runtime');
|
39
|
+
const {
|
40
|
+
ConnectionInterface,
|
41
|
+
getSelector,
|
42
|
+
getValueAtPath,
|
43
|
+
} = require('relay-runtime');
|
44
|
+
|
45
|
+
type LoadMoreFn<TVariables: Variables> = (
|
46
|
+
count: number,
|
47
|
+
options?: {
|
48
|
+
onComplete?: (Error | null) => void,
|
49
|
+
UNSTABLE_extraVariables?: Partial<TVariables>,
|
50
|
+
},
|
51
|
+
) => void;
|
52
|
+
|
53
|
+
export type ReturnType<TVariables, TData, TEdgeData, TKey> = {
|
54
|
+
// NOTE: This type ensures that the type of the returned data is either:
|
55
|
+
// - nullable if the provided ref type is nullable
|
56
|
+
// - non-nullable if the provided ref type is non-nullable
|
57
|
+
data: [+key: TKey] extends [+key: {+$fragmentSpreads: mixed, ...}]
|
58
|
+
? TData
|
59
|
+
: ?TData,
|
60
|
+
loadNext: LoadMoreFn<TVariables>,
|
61
|
+
hasNext: boolean,
|
62
|
+
isLoadingNext: boolean,
|
63
|
+
refetch: RefetchFn<TVariables, TKey>,
|
64
|
+
edges: TEdgeData,
|
65
|
+
};
|
66
|
+
|
67
|
+
type LoadMoreOptions<TVariables> = {
|
68
|
+
UNSTABLE_extraVariables?: Partial<TVariables>,
|
69
|
+
onComplete?: (Error | null) => void,
|
70
|
+
};
|
71
|
+
|
72
|
+
export type GetExtraVariablesFn<TEdgeData, TData, TVariables, TKey> = ({
|
73
|
+
hasNext: boolean,
|
74
|
+
data: [+key: TKey] extends [+key: {+$fragmentSpreads: mixed, ...}]
|
75
|
+
? TData
|
76
|
+
: ?TData,
|
77
|
+
getServerEdges: () => TEdgeData,
|
78
|
+
}) => Partial<TVariables>;
|
79
|
+
|
80
|
+
hook usePrefetchableForwardPaginationFragment_EXPERIMENTAL<
|
81
|
+
TFragmentType: FragmentType,
|
82
|
+
TVariables: Variables,
|
83
|
+
TData,
|
84
|
+
TEdgeData,
|
85
|
+
TKey: ?{+$fragmentSpreads: TFragmentType, ...},
|
86
|
+
>(
|
87
|
+
fragmentInput: PrefetchableRefetchableFragment<
|
88
|
+
TFragmentType,
|
89
|
+
TData,
|
90
|
+
TEdgeData,
|
91
|
+
TVariables,
|
92
|
+
>,
|
93
|
+
parentFragmentRef: TKey,
|
94
|
+
bufferSize: number,
|
95
|
+
initialSize?: ?number,
|
96
|
+
prefetchingLoadMoreOptions?: {
|
97
|
+
UNSTABLE_extraVariables?:
|
98
|
+
| Partial<TVariables>
|
99
|
+
| GetExtraVariablesFn<TEdgeData, TData, TVariables, TKey>,
|
100
|
+
onComplete?: (Error | null) => void,
|
101
|
+
},
|
102
|
+
minimalFetchSize: number = 1,
|
103
|
+
): ReturnType<TVariables, TData, TEdgeData, TKey> {
|
104
|
+
const fragmentNode = getFragment(fragmentInput);
|
105
|
+
useStaticFragmentNodeWarning(
|
106
|
+
fragmentNode,
|
107
|
+
'first argument of usePrefetchableForwardPaginationFragment_EXPERIMENTAL()',
|
108
|
+
);
|
109
|
+
const componentDisplayName =
|
110
|
+
'usePrefetchableForwardPaginationFragment_EXPERIMENTAL()';
|
111
|
+
|
112
|
+
const {connectionPathInFragmentData, paginationRequest, paginationMetadata} =
|
113
|
+
getPaginationMetadata(fragmentNode, componentDisplayName);
|
114
|
+
|
115
|
+
const {fragmentData, fragmentRef, refetch} = useRefetchableFragmentInternal<
|
116
|
+
{variables: TVariables, response: TData},
|
117
|
+
{data?: TData},
|
118
|
+
>(fragmentNode, parentFragmentRef, componentDisplayName);
|
119
|
+
// TODO: Get rid of `getFragmentIdentifier`
|
120
|
+
const fragmentIdentifier = getFragmentIdentifier(fragmentNode, fragmentRef);
|
121
|
+
|
122
|
+
const edgeKeys = useMemo(() => {
|
123
|
+
const connection = getValueAtPath(
|
124
|
+
fragmentData,
|
125
|
+
connectionPathInFragmentData,
|
126
|
+
);
|
127
|
+
if (connection == null) {
|
128
|
+
return null;
|
129
|
+
}
|
130
|
+
const {EDGES} = ConnectionInterface.get();
|
131
|
+
// $FlowFixMe[incompatible-use]
|
132
|
+
return connection[EDGES];
|
133
|
+
}, [connectionPathInFragmentData, fragmentData]);
|
134
|
+
|
135
|
+
const sourceSize = edgeKeys == null ? -1 : edgeKeys.length;
|
136
|
+
|
137
|
+
const [_numInUse, setNumInUse] = useState(
|
138
|
+
initialSize != null ? initialSize : sourceSize,
|
139
|
+
);
|
140
|
+
let numInUse = _numInUse;
|
141
|
+
// We can only reset the source size when the component is
|
142
|
+
// updated with new edgeKeys
|
143
|
+
if (_numInUse === -1 && sourceSize !== -1) {
|
144
|
+
numInUse = initialSize != null ? initialSize : sourceSize;
|
145
|
+
setNumInUse(numInUse);
|
146
|
+
}
|
147
|
+
|
148
|
+
const environment = useRelayEnvironment();
|
149
|
+
const [isLoadingMore, reallySetIsLoadingMore] = useState(false);
|
150
|
+
const [isRefetching, setIsRefetching] = useState(false);
|
151
|
+
const availableSizeRef = useRef(0);
|
152
|
+
// Schedule this update since it must be observed by components at the same
|
153
|
+
// batch as when hasNext changes. hasNext is read from the store and store
|
154
|
+
// updates are scheduled, so this must be scheduled too.
|
155
|
+
const setIsLoadingMore = useCallback(
|
156
|
+
(value: boolean) => {
|
157
|
+
const schedule = environment.getScheduler()?.schedule;
|
158
|
+
if (schedule) {
|
159
|
+
schedule(() => {
|
160
|
+
reallySetIsLoadingMore(value);
|
161
|
+
});
|
162
|
+
} else {
|
163
|
+
reallySetIsLoadingMore(value);
|
164
|
+
}
|
165
|
+
},
|
166
|
+
[environment],
|
167
|
+
);
|
168
|
+
|
169
|
+
// `isLoadingMore` state is updated in a low priority, internally we need
|
170
|
+
// to synchronously get the loading state to decide whether to load more
|
171
|
+
const isLoadingMoreRef = useRef(false);
|
172
|
+
|
173
|
+
const observer = useMemo(
|
174
|
+
() => ({
|
175
|
+
start: () => {
|
176
|
+
isLoadingMoreRef.current = true;
|
177
|
+
// We want to make sure that `isLoadingMore` is updated immediately, to avoid
|
178
|
+
// product code triggering multiple `loadMore` calls
|
179
|
+
reallySetIsLoadingMore(true);
|
180
|
+
},
|
181
|
+
complete: () => {
|
182
|
+
isLoadingMoreRef.current = false;
|
183
|
+
setIsLoadingMore(false);
|
184
|
+
},
|
185
|
+
error: () => {
|
186
|
+
isLoadingMoreRef.current = false;
|
187
|
+
setIsLoadingMore(false);
|
188
|
+
},
|
189
|
+
}),
|
190
|
+
[setIsLoadingMore],
|
191
|
+
);
|
192
|
+
const handleReset = useCallback(() => {
|
193
|
+
if (!isRefetching) {
|
194
|
+
// Do not reset items count during refetching
|
195
|
+
const schedule = environment.getScheduler()?.schedule;
|
196
|
+
if (schedule) {
|
197
|
+
schedule(() => {
|
198
|
+
setNumInUse(-1);
|
199
|
+
});
|
200
|
+
} else {
|
201
|
+
setNumInUse(-1);
|
202
|
+
}
|
203
|
+
}
|
204
|
+
isLoadingMoreRef.current = false;
|
205
|
+
setIsLoadingMore(false);
|
206
|
+
}, [environment, isRefetching, setIsLoadingMore]);
|
207
|
+
|
208
|
+
const [loadMore, hasNext, disposeFetchNext] = useLoadMoreFunction<TVariables>(
|
209
|
+
{
|
210
|
+
componentDisplayName,
|
211
|
+
connectionPathInFragmentData,
|
212
|
+
direction: 'forward',
|
213
|
+
fragmentData,
|
214
|
+
fragmentIdentifier,
|
215
|
+
fragmentNode,
|
216
|
+
fragmentRef,
|
217
|
+
paginationMetadata,
|
218
|
+
paginationRequest,
|
219
|
+
observer,
|
220
|
+
onReset: handleReset,
|
221
|
+
},
|
222
|
+
);
|
223
|
+
|
224
|
+
useLayoutEffect(() => {
|
225
|
+
// Make sure `availableSize` is updated before `showMore` from current render can be called
|
226
|
+
availableSizeRef.current = sourceSize - numInUse;
|
227
|
+
}, [numInUse, sourceSize]);
|
228
|
+
|
229
|
+
const prefetchingUNSTABLE_extraVariables =
|
230
|
+
prefetchingLoadMoreOptions?.UNSTABLE_extraVariables;
|
231
|
+
const prefetchingOnComplete = prefetchingLoadMoreOptions?.onComplete;
|
232
|
+
|
233
|
+
const showMore = useCallback(
|
234
|
+
(numToAdd: number, options?: LoadMoreOptions<TVariables>) => {
|
235
|
+
// Matches the behavior of `usePaginationFragment`. If there is a `loadMore` ongoing,
|
236
|
+
// the hook handles making the `loadMore` a no-op.
|
237
|
+
if (!isLoadingMoreRef.current || availableSizeRef.current >= 0) {
|
238
|
+
// Preemtively update `availableSizeRef`, so if two `loadMore` is called in the same tick,
|
239
|
+
// a second `loadMore` can be no-op
|
240
|
+
availableSizeRef.current -= numToAdd;
|
241
|
+
|
242
|
+
setNumInUse(lastNumInUse => {
|
243
|
+
return lastNumInUse + numToAdd;
|
244
|
+
});
|
245
|
+
|
246
|
+
// If the product needs more items from network, load the amount needed to fullfil
|
247
|
+
// the requirement and cache, capped at the current amount defined by product
|
248
|
+
if (!isLoadingMoreRef.current && availableSizeRef.current < 0) {
|
249
|
+
loadMore(
|
250
|
+
Math.max(
|
251
|
+
minimalFetchSize,
|
252
|
+
Math.min(numToAdd, bufferSize - availableSizeRef.current),
|
253
|
+
),
|
254
|
+
// Keep options For backward compatibility
|
255
|
+
options ?? {
|
256
|
+
onComplete: prefetchingOnComplete,
|
257
|
+
UNSTABLE_extraVariables:
|
258
|
+
typeof prefetchingUNSTABLE_extraVariables === 'function'
|
259
|
+
? // $FlowFixMe[incompatible-call]
|
260
|
+
prefetchingUNSTABLE_extraVariables({
|
261
|
+
hasNext,
|
262
|
+
// $FlowFixMe[incompatible-call]
|
263
|
+
data: fragmentData,
|
264
|
+
getServerEdges: () => {
|
265
|
+
const selector = getSelector(
|
266
|
+
// $FlowFixMe[incompatible-call]
|
267
|
+
edgesFragment,
|
268
|
+
edgeKeys,
|
269
|
+
);
|
270
|
+
if (selector == null) {
|
271
|
+
// $FlowFixMe[incompatible-call]
|
272
|
+
return [];
|
273
|
+
}
|
274
|
+
invariant(
|
275
|
+
selector.kind === 'PluralReaderSelector',
|
276
|
+
'Expected a plural selector',
|
277
|
+
);
|
278
|
+
// $FlowFixMe[incompatible-call]
|
279
|
+
return selector.selectors.map(
|
280
|
+
sel => environment.lookup(sel).data,
|
281
|
+
);
|
282
|
+
},
|
283
|
+
})
|
284
|
+
: prefetchingUNSTABLE_extraVariables,
|
285
|
+
},
|
286
|
+
);
|
287
|
+
}
|
288
|
+
}
|
289
|
+
},
|
290
|
+
[
|
291
|
+
bufferSize,
|
292
|
+
loadMore,
|
293
|
+
minimalFetchSize,
|
294
|
+
edgeKeys,
|
295
|
+
fragmentData,
|
296
|
+
prefetchingUNSTABLE_extraVariables,
|
297
|
+
prefetchingOnComplete,
|
298
|
+
],
|
299
|
+
);
|
300
|
+
|
301
|
+
const edgesFragment = fragmentInput.metadata?.refetch?.edgesFragment;
|
302
|
+
invariant(
|
303
|
+
edgesFragment != null,
|
304
|
+
'usePrefetchableForwardPaginationFragment_EXPERIMENTAL: Expected the edge fragment to be defined, ' +
|
305
|
+
'please make sure you have added `prefetchable_pagination: true` to `@connection`',
|
306
|
+
);
|
307
|
+
|
308
|
+
// Always try to keep `bufferSize` items in the buffer
|
309
|
+
// Or load the number of items that have been registred to show
|
310
|
+
useEffect(() => {
|
311
|
+
if (
|
312
|
+
// Check the ref to avoid infinite `loadMore`, when a `loadMore` has started,
|
313
|
+
// but `isLoadingMore` isn't updated
|
314
|
+
!isLoadingMoreRef.current &&
|
315
|
+
// Check the original `isLoadingMore` so when `loadMore` is called, the internal
|
316
|
+
// `loadMore` hook has been updated with the latest cursor
|
317
|
+
!isLoadingMore &&
|
318
|
+
!isRefetching &&
|
319
|
+
hasNext &&
|
320
|
+
(sourceSize - numInUse < bufferSize || numInUse > sourceSize)
|
321
|
+
) {
|
322
|
+
const onComplete = prefetchingOnComplete;
|
323
|
+
loadMore(
|
324
|
+
Math.max(
|
325
|
+
bufferSize - Math.max(sourceSize - numInUse, 0),
|
326
|
+
numInUse - sourceSize,
|
327
|
+
minimalFetchSize,
|
328
|
+
),
|
329
|
+
{
|
330
|
+
onComplete,
|
331
|
+
UNSTABLE_extraVariables:
|
332
|
+
typeof prefetchingUNSTABLE_extraVariables === 'function'
|
333
|
+
? // $FlowFixMe[incompatible-call]
|
334
|
+
prefetchingUNSTABLE_extraVariables({
|
335
|
+
hasNext,
|
336
|
+
// $FlowFixMe[incompatible-call]
|
337
|
+
data: fragmentData,
|
338
|
+
getServerEdges: () => {
|
339
|
+
const selector = getSelector(edgesFragment, edgeKeys);
|
340
|
+
if (selector == null) {
|
341
|
+
// $FlowFixMe[incompatible-call]
|
342
|
+
return [];
|
343
|
+
}
|
344
|
+
invariant(
|
345
|
+
selector.kind === 'PluralReaderSelector',
|
346
|
+
'Expected a plural selector',
|
347
|
+
);
|
348
|
+
// $FlowFixMe[incompatible-call]
|
349
|
+
return selector.selectors.map(
|
350
|
+
sel => environment.lookup(sel).data,
|
351
|
+
);
|
352
|
+
},
|
353
|
+
})
|
354
|
+
: prefetchingUNSTABLE_extraVariables,
|
355
|
+
},
|
356
|
+
);
|
357
|
+
}
|
358
|
+
}, [
|
359
|
+
hasNext,
|
360
|
+
bufferSize,
|
361
|
+
isRefetching,
|
362
|
+
loadMore,
|
363
|
+
numInUse,
|
364
|
+
prefetchingUNSTABLE_extraVariables,
|
365
|
+
prefetchingOnComplete,
|
366
|
+
sourceSize,
|
367
|
+
edgeKeys,
|
368
|
+
isLoadingMore,
|
369
|
+
minimalFetchSize,
|
370
|
+
environment,
|
371
|
+
edgesFragment,
|
372
|
+
]);
|
373
|
+
|
374
|
+
const realNumInUse = Math.min(numInUse, sourceSize);
|
375
|
+
|
376
|
+
const derivedEdgeKeys: $ReadOnlyArray<mixed> = useMemo(
|
377
|
+
() => edgeKeys?.slice(0, realNumInUse) ?? [],
|
378
|
+
[edgeKeys, realNumInUse],
|
379
|
+
);
|
380
|
+
|
381
|
+
// $FlowExpectedError[incompatible-call] - we know derivedEdgeKeys are the correct keys
|
382
|
+
const edges: TEdgeData = useFragment(edgesFragment, derivedEdgeKeys);
|
383
|
+
|
384
|
+
const refetchPagination = useCallback(
|
385
|
+
(variables: TVariables, options?: Options) => {
|
386
|
+
disposeFetchNext();
|
387
|
+
setIsRefetching(true);
|
388
|
+
return refetch(variables, {
|
389
|
+
...options,
|
390
|
+
onComplete: maybeError => {
|
391
|
+
// Need to be batched with the store update
|
392
|
+
const schedule = environment.getScheduler()?.schedule;
|
393
|
+
if (schedule) {
|
394
|
+
schedule(() => {
|
395
|
+
setIsRefetching(false);
|
396
|
+
setNumInUse(-1);
|
397
|
+
});
|
398
|
+
} else {
|
399
|
+
setIsRefetching(false);
|
400
|
+
setNumInUse(-1);
|
401
|
+
}
|
402
|
+
options?.onComplete?.(maybeError);
|
403
|
+
},
|
404
|
+
__environment: undefined,
|
405
|
+
});
|
406
|
+
},
|
407
|
+
[disposeFetchNext, environment, refetch],
|
408
|
+
);
|
409
|
+
|
410
|
+
if (__DEV__) {
|
411
|
+
// $FlowFixMe[react-rule-hook]
|
412
|
+
useDebugValue({
|
413
|
+
fragment: fragmentNode.name,
|
414
|
+
data: fragmentData,
|
415
|
+
hasNext,
|
416
|
+
isLoadingNext: isLoadingMore,
|
417
|
+
});
|
418
|
+
}
|
419
|
+
|
420
|
+
return {
|
421
|
+
edges,
|
422
|
+
// $FlowFixMe[incompatible-return]
|
423
|
+
data: fragmentData,
|
424
|
+
loadNext: showMore,
|
425
|
+
hasNext: hasNext || sourceSize > numInUse,
|
426
|
+
// Only reflect `isLoadingMore` if the product depends on it, do not refelect
|
427
|
+
// `isLoaindgMore` state if it is for fufilling the buffer
|
428
|
+
isLoadingNext: isLoadingMore && numInUse > sourceSize,
|
429
|
+
refetch: refetchPagination,
|
430
|
+
};
|
431
|
+
}
|
432
|
+
|
433
|
+
module.exports = usePrefetchableForwardPaginationFragment_EXPERIMENTAL;
|