react-relay 18.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.
Files changed (32) hide show
  1. package/ReactRelayContext.js +1 -1
  2. package/buildReactRelayContainer.js.flow +1 -0
  3. package/hooks.js +1 -1
  4. package/index.js +1 -1
  5. package/legacy.js +1 -1
  6. package/lib/relay-hooks/getConnectionState.js +47 -0
  7. package/lib/relay-hooks/legacy/FragmentResource.js +2 -6
  8. package/lib/relay-hooks/readFragmentInternal.js +2 -4
  9. package/lib/relay-hooks/useFragmentInternal.js +1 -1
  10. package/lib/relay-hooks/useFragmentInternal_CURRENT.js +2 -8
  11. package/lib/relay-hooks/useFragmentInternal_EXPERIMENTAL.js +5 -26
  12. package/lib/relay-hooks/useLoadMoreFunction.js +10 -43
  13. package/lib/relay-hooks/useLoadMoreFunction_EXPERIMENTAL.js +130 -0
  14. package/lib/relay-hooks/useQueryLoader.js +8 -0
  15. package/lib/relay-hooks/useQueryLoader_EXPERIMENTAL.js +120 -0
  16. package/package.json +2 -2
  17. package/react-relay-hooks.js +2 -2
  18. package/react-relay-hooks.min.js +2 -2
  19. package/react-relay-legacy.js +1 -1
  20. package/react-relay-legacy.min.js +1 -1
  21. package/react-relay.js +2 -2
  22. package/react-relay.min.js +2 -2
  23. package/relay-hooks/getConnectionState.js.flow +97 -0
  24. package/relay-hooks/legacy/FragmentResource.js.flow +2 -13
  25. package/relay-hooks/readFragmentInternal.js.flow +1 -10
  26. package/relay-hooks/useFragmentInternal.js.flow +1 -1
  27. package/relay-hooks/useFragmentInternal_CURRENT.js.flow +2 -15
  28. package/relay-hooks/useFragmentInternal_EXPERIMENTAL.js.flow +3 -49
  29. package/relay-hooks/useLoadMoreFunction.js.flow +14 -80
  30. package/relay-hooks/useLoadMoreFunction_EXPERIMENTAL.js.flow +280 -0
  31. package/relay-hooks/useQueryLoader.js.flow +27 -3
  32. package/relay-hooks/useQueryLoader_EXPERIMENTAL.js.flow +253 -0
@@ -127,20 +127,11 @@ function handlePotentialSnapshotErrorsForState(
127
127
  if (state.kind === 'singular') {
128
128
  handlePotentialSnapshotErrors(
129
129
  environment,
130
- state.snapshot.missingRequiredFields,
131
- state.snapshot.relayResolverErrors,
132
130
  state.snapshot.errorResponseFields,
133
- state.snapshot.selector.node.metadata?.throwOnFieldError ?? false,
134
131
  );
135
132
  } else if (state.kind === 'plural') {
136
133
  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
- );
134
+ handlePotentialSnapshotErrors(environment, snapshot.errorResponseFields);
144
135
  }
145
136
  }
146
137
  }
@@ -176,8 +167,6 @@ function handleMissedUpdates(
176
167
  missingLiveResolverFields: currentSnapshot.missingLiveResolverFields,
177
168
  seenRecords: currentSnapshot.seenRecords,
178
169
  selector: currentSnapshot.selector,
179
- missingRequiredFields: currentSnapshot.missingRequiredFields,
180
- relayResolverErrors: currentSnapshot.relayResolverErrors,
181
170
  errorResponseFields: currentSnapshot.errorResponseFields,
182
171
  };
183
172
  return [
@@ -204,8 +193,6 @@ function handleMissedUpdates(
204
193
  missingLiveResolverFields: currentSnapshot.missingLiveResolverFields,
205
194
  seenRecords: currentSnapshot.seenRecords,
206
195
  selector: currentSnapshot.selector,
207
- missingRequiredFields: currentSnapshot.missingRequiredFields,
208
- relayResolverErrors: currentSnapshot.relayResolverErrors,
209
196
  errorResponseFields: currentSnapshot.errorResponseFields,
210
197
  };
211
198
  if (updatedData !== snapshot.data) {
@@ -271,7 +258,6 @@ function subscribeToSnapshot(
271
258
  environment: IEnvironment,
272
259
  state: FragmentState,
273
260
  setState: StateUpdaterFunction<FragmentState>,
274
- pendingStateRef: {current: number | null},
275
261
  ): () => void {
276
262
  if (state.kind === 'bailout') {
277
263
  return () => {};
@@ -307,8 +293,6 @@ function subscribeToSnapshot(
307
293
  environment: state.environment,
308
294
  };
309
295
  }
310
- pendingStateRef.current =
311
- nextState.kind === 'singular' ? nextState.epoch : null;
312
296
  return nextState;
313
297
  });
314
298
  });
@@ -353,8 +337,6 @@ function subscribeToSnapshot(
353
337
  environment: state.environment,
354
338
  };
355
339
  }
356
- pendingStateRef.current =
357
- nextState.kind === 'plural' ? nextState.epoch : null;
358
340
  return nextState;
359
341
  });
360
342
  }),
@@ -542,7 +524,7 @@ hook useFragmentInternal_EXPERIMENTAL(
542
524
  if (suspendingLiveResolvers != null && suspendingLiveResolvers.length > 0) {
543
525
  throw Promise.all(
544
526
  suspendingLiveResolvers.map(({liveStateID}) => {
545
- // $FlowFixMe[prop-missing] This is expected to be a LiveResolverStore
527
+ // $FlowFixMe[prop-missing] This is expected to be a RelayModernStore
546
528
  return environment.getStore().getLiveResolverPromise(liveStateID);
547
529
  }),
548
530
  );
@@ -578,11 +560,6 @@ hook useFragmentInternal_EXPERIMENTAL(
578
560
  // they're missing even though we are out of options for possibly fetching them:
579
561
  handlePotentialSnapshotErrorsForState(environment, state);
580
562
 
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
563
  // We emulate CRUD effects using a ref and two effects:
587
564
  // - The ref tracks the current state (including updates from the subscription)
588
565
  // and the dispose function for the current subscription. This is null until
@@ -647,7 +624,6 @@ hook useFragmentInternal_EXPERIMENTAL(
647
624
  state.environment,
648
625
  stateForSubscription,
649
626
  setState,
650
- pendingStateEpochRef,
651
627
  );
652
628
  storeSubscriptionRef.current = {
653
629
  dispose,
@@ -657,12 +633,7 @@ hook useFragmentInternal_EXPERIMENTAL(
657
633
  }, [state]);
658
634
  useEffect(() => {
659
635
  if (storeSubscriptionRef.current == null && state.kind !== 'bailout') {
660
- const dispose = subscribeToSnapshot(
661
- state.environment,
662
- state,
663
- setState,
664
- pendingStateEpochRef,
665
- );
636
+ const dispose = subscribeToSnapshot(state.environment, state, setState);
666
637
  storeSubscriptionRef.current = {
667
638
  dispose,
668
639
  selector: state.selector,
@@ -677,23 +648,6 @@ hook useFragmentInternal_EXPERIMENTAL(
677
648
  // simulating a CRUD effect
678
649
  }, []);
679
650
 
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
651
  let data: ?SelectorData | Array<?SelectorData>;
698
652
  if (isPlural) {
699
653
  // 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
- ConnectionInterface,
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;
@@ -0,0 +1,280 @@
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 {
15
+ ConcreteRequest,
16
+ Direction,
17
+ Disposable,
18
+ GraphQLResponse,
19
+ Observer,
20
+ ReaderFragment,
21
+ ReaderPaginationMetadata,
22
+ Subscription,
23
+ Variables,
24
+ } from 'relay-runtime';
25
+
26
+ const getConnectionState = require('./getConnectionState');
27
+ const useIsMountedRef = require('./useIsMountedRef');
28
+ const useIsOperationNodeActive = require('./useIsOperationNodeActive');
29
+ const useRelayEnvironment = require('./useRelayEnvironment');
30
+ const invariant = require('invariant');
31
+ const {useCallback, useRef, useState} = require('react');
32
+ const {
33
+ __internal: {fetchQuery},
34
+ createOperationDescriptor,
35
+ getPaginationVariables,
36
+ getRefetchMetadata,
37
+ getSelector,
38
+ } = require('relay-runtime');
39
+ const warning = require('warning');
40
+
41
+ export type LoadMoreFn<TVariables: Variables> = (
42
+ count: number,
43
+ options?: {
44
+ onComplete?: (Error | null) => void,
45
+ UNSTABLE_extraVariables?: Partial<TVariables>,
46
+ },
47
+ ) => Disposable;
48
+
49
+ export type UseLoadMoreFunctionArgs = {
50
+ direction: Direction,
51
+ fragmentNode: ReaderFragment,
52
+ fragmentRef: mixed,
53
+ fragmentIdentifier: string,
54
+ fragmentData: mixed,
55
+ connectionPathInFragmentData: $ReadOnlyArray<string | number>,
56
+ paginationRequest: ConcreteRequest,
57
+ paginationMetadata: ReaderPaginationMetadata,
58
+ componentDisplayName: string,
59
+ observer: Observer<GraphQLResponse>,
60
+ onReset: () => void,
61
+ };
62
+
63
+ hook useLoadMoreFunction_EXPERIMENTAL<TVariables: Variables>(
64
+ args: UseLoadMoreFunctionArgs,
65
+ ): [
66
+ // Function to load more data
67
+ LoadMoreFn<TVariables>,
68
+ // Whether the connection has more data to load
69
+ boolean,
70
+ // Force dispose function which cancels the in-flight fetch itself, and callbacks
71
+ () => void,
72
+ ] {
73
+ const {
74
+ direction,
75
+ fragmentNode,
76
+ fragmentRef,
77
+ fragmentIdentifier,
78
+ fragmentData,
79
+ connectionPathInFragmentData,
80
+ paginationRequest,
81
+ paginationMetadata,
82
+ componentDisplayName,
83
+ observer,
84
+ onReset,
85
+ } = args;
86
+ const environment = useRelayEnvironment();
87
+
88
+ const {identifierInfo} = getRefetchMetadata(
89
+ fragmentNode,
90
+ componentDisplayName,
91
+ );
92
+ const identifierValue =
93
+ identifierInfo?.identifierField != null &&
94
+ fragmentData != null &&
95
+ typeof fragmentData === 'object'
96
+ ? fragmentData[identifierInfo.identifierField]
97
+ : null;
98
+
99
+ const fetchStatusRef = useRef<
100
+ {kind: 'fetching', subscription: Subscription} | {kind: 'none'},
101
+ >({kind: 'none'});
102
+ const [mirroredEnvironment, setMirroredEnvironment] = useState(environment);
103
+ const [mirroredFragmentIdentifier, setMirroredFragmentIdentifier] =
104
+ useState(fragmentIdentifier);
105
+
106
+ const isParentQueryActive = useIsOperationNodeActive(
107
+ fragmentNode,
108
+ fragmentRef,
109
+ );
110
+
111
+ const forceDisposeFn = useCallback(() => {
112
+ // $FlowFixMe[react-rule-unsafe-ref]
113
+ if (fetchStatusRef.current.kind === 'fetching') {
114
+ // $FlowFixMe[react-rule-unsafe-ref]
115
+ fetchStatusRef.current.subscription.unsubscribe();
116
+ }
117
+ // $FlowFixMe[react-rule-unsafe-ref]
118
+ fetchStatusRef.current = {kind: 'none'};
119
+ }, []);
120
+
121
+ const shouldReset =
122
+ environment !== mirroredEnvironment ||
123
+ fragmentIdentifier !== mirroredFragmentIdentifier;
124
+ if (shouldReset) {
125
+ forceDisposeFn();
126
+ onReset();
127
+ setMirroredEnvironment(environment);
128
+ setMirroredFragmentIdentifier(fragmentIdentifier);
129
+ }
130
+
131
+ const {cursor, hasMore} = getConnectionState(
132
+ direction,
133
+ fragmentNode,
134
+ fragmentData,
135
+ connectionPathInFragmentData,
136
+ );
137
+
138
+ const isMountedRef = useIsMountedRef();
139
+ const loadMore = useCallback(
140
+ (
141
+ count: number,
142
+ options: void | {
143
+ UNSTABLE_extraVariables?: Partial<TVariables>,
144
+ onComplete?: (Error | null) => void,
145
+ },
146
+ ) => {
147
+ // TODO(T41131846): Fetch/Caching policies for loadMore
148
+
149
+ const onComplete = options?.onComplete;
150
+ if (isMountedRef.current !== true) {
151
+ // Bail out and warn if we're trying to paginate after the component
152
+ // has unmounted
153
+ warning(
154
+ false,
155
+ 'Relay: Unexpected fetch on unmounted component for fragment ' +
156
+ '`%s` in `%s`. It looks like some instances of your component are ' +
157
+ 'still trying to fetch data but they already unmounted. ' +
158
+ 'Please make sure you clear all timers, intervals, ' +
159
+ 'async calls, etc that may trigger a fetch.',
160
+ fragmentNode.name,
161
+ componentDisplayName,
162
+ );
163
+ return {dispose: () => {}};
164
+ }
165
+
166
+ const fragmentSelector = getSelector(fragmentNode, fragmentRef);
167
+ if (
168
+ fetchStatusRef.current.kind === 'fetching' ||
169
+ fragmentData == null ||
170
+ isParentQueryActive
171
+ ) {
172
+ if (fragmentSelector == null) {
173
+ warning(
174
+ false,
175
+ 'Relay: Unexpected fetch while using a null fragment ref ' +
176
+ 'for fragment `%s` in `%s`. When fetching more items, we expect ' +
177
+ "initial fragment data to be non-null. Please make sure you're " +
178
+ 'passing a valid fragment ref to `%s` before paginating.',
179
+ fragmentNode.name,
180
+ componentDisplayName,
181
+ componentDisplayName,
182
+ );
183
+ }
184
+
185
+ if (onComplete) {
186
+ onComplete(null);
187
+ }
188
+ return {dispose: () => {}};
189
+ }
190
+
191
+ invariant(
192
+ fragmentSelector != null &&
193
+ fragmentSelector.kind !== 'PluralReaderSelector',
194
+ 'Relay: Expected to be able to find a non-plural fragment owner for ' +
195
+ "fragment `%s` when using `%s`. If you're seeing this, " +
196
+ 'this is likely a bug in Relay.',
197
+ fragmentNode.name,
198
+ componentDisplayName,
199
+ );
200
+
201
+ const parentVariables = fragmentSelector.owner.variables;
202
+ const fragmentVariables = fragmentSelector.variables;
203
+ const extraVariables = options?.UNSTABLE_extraVariables;
204
+ const baseVariables = {
205
+ ...parentVariables,
206
+ ...fragmentVariables,
207
+ };
208
+ const paginationVariables = getPaginationVariables(
209
+ direction,
210
+ count,
211
+ cursor,
212
+ baseVariables,
213
+ {...extraVariables},
214
+ paginationMetadata,
215
+ );
216
+
217
+ // If the query needs an identifier value ('id' or similar) and one
218
+ // was not explicitly provided, read it from the fragment data.
219
+ if (identifierInfo != null) {
220
+ // @refetchable fragments are guaranteed to have an `id` selection
221
+ // if the type is Node, implements Node, or is @fetchable. Double-check
222
+ // that there actually is a value at runtime.
223
+ if (typeof identifierValue !== 'string') {
224
+ warning(
225
+ false,
226
+ 'Relay: Expected result to have a string ' +
227
+ '`%s` in order to refetch, got `%s`.',
228
+ identifierInfo.identifierField,
229
+ identifierValue,
230
+ );
231
+ }
232
+ paginationVariables[identifierInfo.identifierQueryVariableName] =
233
+ identifierValue;
234
+ }
235
+
236
+ const paginationQuery = createOperationDescriptor(
237
+ paginationRequest,
238
+ paginationVariables,
239
+ {force: true},
240
+ );
241
+ fetchQuery(environment, paginationQuery).subscribe({
242
+ ...observer,
243
+ start: subscription => {
244
+ fetchStatusRef.current = {kind: 'fetching', subscription};
245
+ observer.start && observer.start(subscription);
246
+ },
247
+ complete: () => {
248
+ fetchStatusRef.current = {kind: 'none'};
249
+ observer.complete && observer.complete();
250
+ onComplete && onComplete(null);
251
+ },
252
+ error: error => {
253
+ fetchStatusRef.current = {kind: 'none'};
254
+ observer.complete && observer.complete();
255
+ onComplete && onComplete(error);
256
+ },
257
+ });
258
+ return {
259
+ dispose: () => {},
260
+ };
261
+ },
262
+ // NOTE: We disable react-hooks-deps warning because all values
263
+ // inside paginationMetadata are static
264
+ // eslint-disable-next-line react-hooks/exhaustive-deps
265
+ [
266
+ environment,
267
+ identifierValue,
268
+ direction,
269
+ cursor,
270
+ isParentQueryActive,
271
+ fragmentData,
272
+ fragmentNode.name,
273
+ fragmentRef,
274
+ componentDisplayName,
275
+ ],
276
+ );
277
+ return [loadMore, hasMore, forceDisposeFn];
278
+ }
279
+
280
+ module.exports = useLoadMoreFunction_EXPERIMENTAL;
@@ -25,9 +25,10 @@ import type {
25
25
 
26
26
  const {loadQuery} = require('./loadQuery');
27
27
  const useIsMountedRef = require('./useIsMountedRef');
28
+ const useQueryLoader_EXPERIMENTAL = require('./useQueryLoader_EXPERIMENTAL');
28
29
  const useRelayEnvironment = require('./useRelayEnvironment');
29
30
  const {useCallback, useEffect, useRef, useState} = require('react');
30
- const {getRequest} = require('relay-runtime');
31
+ const {RelayFeatureFlags, getRequest} = require('relay-runtime');
31
32
 
32
33
  export type LoaderFn<TQuery: OperationType> = (
33
34
  variables: TQuery['variables'],
@@ -42,7 +43,7 @@ export type UseQueryLoaderLoadQueryOptions = $ReadOnly<{
42
43
  // NullQueryReference needs to implement referential equality,
43
44
  // so that multiple NullQueryReferences can be in the same set
44
45
  // (corresponding to multiple calls to disposeQuery).
45
- type NullQueryReference = {
46
+ export type NullQueryReference = {
46
47
  kind: 'NullQueryReference',
47
48
  };
48
49
  const initialNullQueryReferenceState = {kind: 'NullQueryReference'};
@@ -68,7 +69,7 @@ function requestIsLiveQuery<
68
69
  return request.params.metadata.live !== undefined;
69
70
  }
70
71
 
71
- type UseQueryLoaderHookReturnType<
72
+ export type UseQueryLoaderHookReturnType<
72
73
  TVariables: Variables,
73
74
  TData,
74
75
  TRawResponse: ?{...} = void,
@@ -115,6 +116,29 @@ hook useQueryLoader<TVariables: Variables, TData, TRawResponse: ?{...} = void>(
115
116
  variables: TVariables,
116
117
  rawResponse?: $NonMaybeType<TRawResponse>,
117
118
  }>,
119
+ ): UseQueryLoaderHookReturnType<TVariables, TData> {
120
+ if (RelayFeatureFlags.ENABLE_ACTIVITY_COMPATIBILITY) {
121
+ // $FlowFixMe[react-rule-hook] - the condition is static
122
+ return useQueryLoader_EXPERIMENTAL(
123
+ preloadableRequest,
124
+ initialQueryReference,
125
+ );
126
+ }
127
+ // $FlowFixMe[react-rule-hook] - the condition is static
128
+ return useQueryLoader_CURRENT(preloadableRequest, initialQueryReference);
129
+ }
130
+
131
+ hook useQueryLoader_CURRENT<
132
+ TVariables: Variables,
133
+ TData,
134
+ TRawResponse: ?{...} = void,
135
+ >(
136
+ preloadableRequest: Query<TVariables, TData, TRawResponse>,
137
+ initialQueryReference?: ?PreloadedQuery<{
138
+ response: TData,
139
+ variables: TVariables,
140
+ rawResponse?: $NonMaybeType<TRawResponse>,
141
+ }>,
118
142
  ): UseQueryLoaderHookReturnType<TVariables, TData> {
119
143
  type QueryType = {
120
144
  response: TData,