react-relay 18.0.0 → 18.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,