react-relay 16.0.0 → 16.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. package/ReactRelayContext.js +1 -1
  2. package/ReactRelayTypes.js.flow +1 -0
  3. package/hooks.js +1 -1
  4. package/hooks.js.flow +1 -1
  5. package/index.js +1 -1
  6. package/index.js.flow +1 -1
  7. package/legacy.js +1 -1
  8. package/lib/relay-hooks/HooksImplementation.js +1 -1
  9. package/lib/relay-hooks/SuspenseResource.js +7 -4
  10. package/lib/relay-hooks/{react-cache/readFragmentInternal_REACT_CACHE.js → experimental/readFragmentInternal_EXPERIMENTAL.js} +4 -4
  11. package/lib/relay-hooks/{react-cache/useFragmentInternal_REACT_CACHE.js → experimental/useFragmentInternal_EXPERIMENTAL.js} +63 -29
  12. package/lib/relay-hooks/{react-cache/useFragment_REACT_CACHE.js → experimental/useFragment_EXPERIMENTAL.js} +1 -1
  13. package/lib/relay-hooks/{react-cache/usePaginationFragment_REACT_CACHE.js → experimental/usePaginationFragment_EXPERIMENTAL.js} +1 -1
  14. package/lib/relay-hooks/{react-cache/useRefetchableFragmentInternal_REACT_CACHE.js → experimental/useRefetchableFragmentInternal_EXPERIMENTAL.js} +2 -2
  15. package/lib/relay-hooks/{react-cache/useRefetchableFragment_REACT_CACHE.js → experimental/useRefetchableFragment_EXPERIMENTAL.js} +1 -1
  16. package/lib/relay-hooks/{FragmentResource.js → legacy/FragmentResource.js} +7 -6
  17. package/lib/relay-hooks/{useBlockingPaginationFragment.js → legacy/useBlockingPaginationFragment.js} +2 -2
  18. package/lib/relay-hooks/{useFragmentNode.js → legacy/useFragmentNode.js} +2 -2
  19. package/lib/relay-hooks/{useRefetchableFragmentNode.js → legacy/useRefetchableFragmentNode.js} +8 -8
  20. package/lib/relay-hooks/useFragment.js +1 -1
  21. package/lib/relay-hooks/useLazyLoadQueryNode.js +13 -3
  22. package/lib/relay-hooks/usePaginationFragment.js +1 -1
  23. package/lib/relay-hooks/useRefetchableFragment.js +1 -1
  24. package/package.json +2 -2
  25. package/react-relay-hooks.js +2 -2
  26. package/react-relay-hooks.min.js +2 -2
  27. package/react-relay-legacy.js +2 -2
  28. package/react-relay-legacy.min.js +2 -2
  29. package/react-relay.js +2 -2
  30. package/react-relay.min.js +2 -2
  31. package/relay-hooks/EntryPointTypes.flow.js.flow +25 -33
  32. package/relay-hooks/HooksImplementation.js.flow +3 -1
  33. package/relay-hooks/NestedRelayEntryPointBuilderUtils.js.flow +5 -11
  34. package/relay-hooks/SuspenseResource.js.flow +11 -8
  35. package/relay-hooks/__flowtests__/useBlockingPaginationFragment-flowtest.js.flow +1 -1
  36. package/relay-hooks/{react-cache/readFragmentInternal_REACT_CACHE.js.flow → experimental/readFragmentInternal_EXPERIMENTAL.js.flow} +4 -2
  37. package/relay-hooks/{react-cache/useFragmentInternal_REACT_CACHE.js.flow → experimental/useFragmentInternal_EXPERIMENTAL.js.flow} +61 -18
  38. package/relay-hooks/{react-cache/useFragment_REACT_CACHE.js.flow → experimental/useFragment_EXPERIMENTAL.js.flow} +10 -4
  39. package/relay-hooks/{react-cache/usePaginationFragment_REACT_CACHE.js.flow → experimental/usePaginationFragment_EXPERIMENTAL.js.flow} +2 -2
  40. package/relay-hooks/{react-cache/useRefetchableFragmentInternal_REACT_CACHE.js.flow → experimental/useRefetchableFragmentInternal_EXPERIMENTAL.js.flow} +11 -11
  41. package/relay-hooks/{react-cache/useRefetchableFragment_REACT_CACHE.js.flow → experimental/useRefetchableFragment_EXPERIMENTAL.js.flow} +1 -1
  42. package/relay-hooks/{FragmentResource.js.flow → legacy/FragmentResource.js.flow} +8 -5
  43. package/relay-hooks/{useBlockingPaginationFragment.js.flow → legacy/useBlockingPaginationFragment.js.flow} +13 -18
  44. package/relay-hooks/{useFragmentNode.js.flow → legacy/useFragmentNode.js.flow} +2 -2
  45. package/relay-hooks/{useRefetchableFragmentNode.js.flow → legacy/useRefetchableFragmentNode.js.flow} +12 -14
  46. package/relay-hooks/loadQuery.js.flow +1 -1
  47. package/relay-hooks/useFragment.js.flow +10 -4
  48. package/relay-hooks/useLazyLoadQueryNode.js.flow +18 -2
  49. package/relay-hooks/usePaginationFragment.js.flow +7 -9
  50. package/relay-hooks/useRefetchableFragment.js.flow +15 -18
  51. package/lib/relay-hooks/react-cache/RelayReactCache.js +0 -20
  52. package/lib/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js +0 -255
  53. package/lib/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js +0 -33
  54. package/lib/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js +0 -81
  55. package/relay-hooks/react-cache/RelayReactCache.js.flow +0 -40
  56. package/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js.flow +0 -430
  57. package/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js.flow +0 -70
  58. package/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js.flow +0 -150
@@ -31,7 +31,7 @@ const useRelayEnvironment = require('../useRelayEnvironment');
31
31
  const invariant = require('invariant');
32
32
  const {useDebugValue, useEffect, useMemo, useRef, useState} = require('react');
33
33
  const {
34
- __internal: {fetchQuery: fetchQueryInternal},
34
+ __internal: {fetchQuery: fetchQueryInternal, getPromiseForActiveRequest},
35
35
  RelayFeatureFlags,
36
36
  areEqualSelectors,
37
37
  createOperationDescriptor,
@@ -117,6 +117,7 @@ function handlePotentialSnapshotErrorsForState(
117
117
  environment,
118
118
  state.snapshot.missingRequiredFields,
119
119
  state.snapshot.relayResolverErrors,
120
+ state.snapshot.errorResponseFields,
120
121
  );
121
122
  } else if (state.kind === 'plural') {
122
123
  for (const snapshot of state.snapshots) {
@@ -124,6 +125,7 @@ function handlePotentialSnapshotErrorsForState(
124
125
  environment,
125
126
  snapshot.missingRequiredFields,
126
127
  snapshot.relayResolverErrors,
128
+ snapshot.errorResponseFields,
127
129
  );
128
130
  }
129
131
  }
@@ -162,6 +164,7 @@ function handleMissedUpdates(
162
164
  selector: currentSnapshot.selector,
163
165
  missingRequiredFields: currentSnapshot.missingRequiredFields,
164
166
  relayResolverErrors: currentSnapshot.relayResolverErrors,
167
+ errorResponseFields: currentSnapshot.errorResponseFields,
165
168
  };
166
169
  return [
167
170
  updatedData !== state.snapshot.data,
@@ -187,6 +190,7 @@ function handleMissedUpdates(
187
190
  selector: currentSnapshot.selector,
188
191
  missingRequiredFields: currentSnapshot.missingRequiredFields,
189
192
  relayResolverErrors: currentSnapshot.relayResolverErrors,
193
+ errorResponseFields: currentSnapshot.errorResponseFields,
190
194
  };
191
195
  if (updatedData !== snapshot.data) {
192
196
  didMissUpdates = true;
@@ -214,7 +218,7 @@ function handleMissingClientEdge(
214
218
  parentFragmentRef: mixed,
215
219
  missingClientEdgeRequestInfo: MissingClientEdgeRequestInfo,
216
220
  queryOptions?: FragmentQueryOptions,
217
- ): QueryResult {
221
+ ): [QueryResult, ?Promise<mixed>] {
218
222
  const originalVariables = getVariablesFromFragment(
219
223
  parentFragmentNode,
220
224
  parentFragmentRef,
@@ -233,17 +237,23 @@ function handleMissingClientEdge(
233
237
  // according to the component mount/suspense cycle; QueryResource
234
238
  // already handles this by itself.
235
239
  const QueryResource = getQueryResourceForEnvironment(environment);
236
- return QueryResource.prepare(
240
+ const queryResult = QueryResource.prepare(
237
241
  queryOperationDescriptor,
238
242
  fetchQueryInternal(environment, queryOperationDescriptor),
239
243
  queryOptions?.fetchPolicy,
240
244
  );
245
+
246
+ return [
247
+ queryResult,
248
+ getPromiseForActiveRequest(environment, queryOperationDescriptor.request),
249
+ ];
241
250
  }
242
251
 
243
252
  function subscribeToSnapshot(
244
253
  environment: IEnvironment,
245
254
  state: FragmentState,
246
255
  setState: StateUpdaterFunction<FragmentState>,
256
+ hasPendingStateChanges: {current: boolean},
247
257
  ): () => void {
248
258
  if (state.kind === 'bailout') {
249
259
  return () => {};
@@ -264,11 +274,14 @@ function subscribeToSnapshot(
264
274
  name: 'useFragment.subscription.missedUpdates',
265
275
  hasDataChanges: dataChanged,
266
276
  });
277
+ hasPendingStateChanges.current = dataChanged;
267
278
  return dataChanged ? nextState : prevState;
268
279
  } else {
269
280
  return prevState;
270
281
  }
271
282
  }
283
+
284
+ hasPendingStateChanges.current = true;
272
285
  return {
273
286
  kind: 'singular',
274
287
  snapshot: latestSnapshot,
@@ -297,6 +310,8 @@ function subscribeToSnapshot(
297
310
  name: 'useFragment.subscription.missedUpdates',
298
311
  hasDataChanges: dataChanged,
299
312
  });
313
+ hasPendingStateChanges.current =
314
+ hasPendingStateChanges.current || dataChanged;
300
315
  return dataChanged ? nextState : prevState;
301
316
  } else {
302
317
  return prevState;
@@ -304,6 +319,7 @@ function subscribeToSnapshot(
304
319
  }
305
320
  const updated = [...prevState.snapshots];
306
321
  updated[index] = latestSnapshot;
322
+ hasPendingStateChanges.current = true;
307
323
  return {
308
324
  kind: 'plural',
309
325
  snapshots: updated,
@@ -344,7 +360,7 @@ function getFragmentState(
344
360
  }
345
361
 
346
362
  // fragmentNode cannot change during the lifetime of the component, though fragmentRef may change.
347
- function useFragmentInternal_REACT_CACHE(
363
+ function useFragmentInternal_EXPERIMENTAL(
348
364
  fragmentNode: ReaderFragment,
349
365
  fragmentRef: mixed,
350
366
  hookDisplayName: string,
@@ -435,7 +451,7 @@ function useFragmentInternal_REACT_CACHE(
435
451
  // The purpose of this is to detect whether we have ever committed, because we
436
452
  // don't suspend on store updates, only when the component either is first trying
437
453
  // to mount or when the our selector changes. The selector change in particular is
438
- // how we suspend for pagination and refetech. Also, fragment selector can be null
454
+ // how we suspend for pagination and refetch. Also, fragment selector can be null
439
455
  // or undefined, so we use false as a special value to distinguish from all fragment
440
456
  // selectors; false means that the component hasn't mounted yet.
441
457
  const committedFragmentSelectorRef = useRef<false | ?ReaderSelector>(false);
@@ -450,27 +466,34 @@ function useFragmentInternal_REACT_CACHE(
450
466
  // a static (constant) property of the fragment. In practice, this effect will
451
467
  // always or never run for a given invocation of this hook.
452
468
  // eslint-disable-next-line react-hooks/rules-of-hooks
453
- const clientEdgeQueries = useMemo(() => {
469
+ const [clientEdgeQueries, activeRequestPromises] = useMemo(() => {
454
470
  const missingClientEdges = getMissingClientEdges(state);
455
471
  // eslint-disable-next-line no-shadow
456
472
  let clientEdgeQueries;
473
+ const activeRequestPromises = [];
457
474
  if (missingClientEdges?.length) {
458
475
  clientEdgeQueries = ([]: Array<QueryResult>);
459
476
  for (const edge of missingClientEdges) {
460
- clientEdgeQueries.push(
461
- handleMissingClientEdge(
462
- environment,
463
- fragmentNode,
464
- fragmentRef,
465
- edge,
466
- queryOptions,
467
- ),
477
+ const [queryResult, requestPromise] = handleMissingClientEdge(
478
+ environment,
479
+ fragmentNode,
480
+ fragmentRef,
481
+ edge,
482
+ queryOptions,
468
483
  );
484
+ clientEdgeQueries.push(queryResult);
485
+ if (requestPromise != null) {
486
+ activeRequestPromises.push(requestPromise);
487
+ }
469
488
  }
470
489
  }
471
- return clientEdgeQueries;
490
+ return [clientEdgeQueries, activeRequestPromises];
472
491
  }, [state, environment, fragmentNode, fragmentRef, queryOptions]);
473
492
 
493
+ if (activeRequestPromises.length) {
494
+ throw Promise.all(activeRequestPromises);
495
+ }
496
+
474
497
  // See above note
475
498
  // eslint-disable-next-line react-hooks/rules-of-hooks
476
499
  useEffect(() => {
@@ -505,6 +528,7 @@ function useFragmentInternal_REACT_CACHE(
505
528
  // We only suspend when the component is first trying to mount or changing
506
529
  // selectors, not if data becomes missing later:
507
530
  if (
531
+ environment !== previousEnvironment ||
508
532
  !committedFragmentSelectorRef.current ||
509
533
  !areEqualSelectors(committedFragmentSelectorRef.current, fragmentSelector)
510
534
  ) {
@@ -528,6 +552,8 @@ function useFragmentInternal_REACT_CACHE(
528
552
  // they're missing even though we are out of options for possibly fetching them:
529
553
  handlePotentialSnapshotErrorsForState(environment, state);
530
554
 
555
+ const hasPendingStateChanges = useRef<boolean>(false);
556
+
531
557
  useEffect(() => {
532
558
  // Check for updates since the state was rendered
533
559
  let currentState = subscribedState;
@@ -546,12 +572,29 @@ function useFragmentInternal_REACT_CACHE(
546
572
  }
547
573
  currentState = updatedState;
548
574
  }
549
- return subscribeToSnapshot(environment, currentState, setState);
575
+ return subscribeToSnapshot(
576
+ environment,
577
+ currentState,
578
+ setState,
579
+ hasPendingStateChanges,
580
+ );
550
581
  }, [environment, subscribedState]);
551
582
 
583
+ if (hasPendingStateChanges.current) {
584
+ const updates = handleMissedUpdates(environment, state);
585
+ if (updates != null) {
586
+ const [hasStateUpdates, updatedState] = updates;
587
+ if (hasStateUpdates) {
588
+ setState(updatedState);
589
+ state = updatedState;
590
+ }
591
+ }
592
+ hasPendingStateChanges.current = false;
593
+ }
594
+
552
595
  let data: ?SelectorData | Array<?SelectorData>;
553
596
  if (isPlural) {
554
- // Plural fragments require allocating an array of the snasphot data values,
597
+ // Plural fragments require allocating an array of the snapshot data values,
555
598
  // which has to be memoized to avoid triggering downstream re-renders.
556
599
  //
557
600
  // Note that isPlural is a constant property of the fragment and does not change
@@ -614,4 +657,4 @@ function useFragmentInternal_REACT_CACHE(
614
657
  return data;
615
658
  }
616
659
 
617
- module.exports = useFragmentInternal_REACT_CACHE;
660
+ module.exports = useFragmentInternal_EXPERIMENTAL;
@@ -15,7 +15,7 @@ import type {Fragment, FragmentType, GraphQLTaggedNode} from 'relay-runtime';
15
15
 
16
16
  const {useTrackLoadQueryInRender} = require('../loadQuery');
17
17
  const useStaticFragmentNodeWarning = require('../useStaticFragmentNodeWarning');
18
- const useFragmentInternal = require('./useFragmentInternal_REACT_CACHE');
18
+ const useFragmentInternal = require('./useFragmentInternal_EXPERIMENTAL');
19
19
  const {useDebugValue} = require('react');
20
20
  const {getFragment} = require('relay-runtime');
21
21
 
@@ -30,17 +30,23 @@ declare function useFragment<TFragmentType: FragmentType, TData>(
30
30
  key: HasSpread<TFragmentType>,
31
31
  ): TData;
32
32
 
33
+ // if the key is nullable, return nullable value
34
+ declare function useFragment<TFragmentType: FragmentType, TData>(
35
+ fragment: Fragment<TFragmentType, TData>,
36
+ key: ?HasSpread<TFragmentType>,
37
+ ): ?TData;
38
+
33
39
  // if the key is a non-nullable array of keys, return non-nullable array
34
40
  declare function useFragment<TFragmentType: FragmentType, TData>(
35
41
  fragment: Fragment<TFragmentType, TData>,
36
42
  key: $ReadOnlyArray<HasSpread<TFragmentType>>,
37
43
  ): TData;
38
44
 
39
- // if the key is null/void, return null/void value
45
+ // if the key is a nullable array of keys, return nullable array
40
46
  declare function useFragment<TFragmentType: FragmentType, TData>(
41
47
  fragment: Fragment<TFragmentType, TData>,
42
- key: null | void,
43
- ): null | void;
48
+ key: ?$ReadOnlyArray<HasSpread<TFragmentType>>,
49
+ ): ?TData;
44
50
 
45
51
  function useFragment(fragment: GraphQLTaggedNode, key: mixed): mixed {
46
52
  // We need to use this hook in order to be able to track if
@@ -13,7 +13,7 @@
13
13
 
14
14
  import type {LoadMoreFn, UseLoadMoreFunctionArgs} from '../useLoadMoreFunction';
15
15
  import type {ReturnType} from '../usePaginationFragment';
16
- import type {Options} from './useRefetchableFragmentInternal_REACT_CACHE';
16
+ import type {Options} from './useRefetchableFragmentInternal_EXPERIMENTAL';
17
17
  import type {
18
18
  FragmentType,
19
19
  GraphQLResponse,
@@ -25,7 +25,7 @@ import type {
25
25
  const useLoadMoreFunction = require('../useLoadMoreFunction');
26
26
  const useRelayEnvironment = require('../useRelayEnvironment');
27
27
  const useStaticFragmentNodeWarning = require('../useStaticFragmentNodeWarning');
28
- const useRefetchableFragmentInternal = require('./useRefetchableFragmentInternal_REACT_CACHE');
28
+ const useRefetchableFragmentInternal = require('./useRefetchableFragmentInternal_EXPERIMENTAL');
29
29
  const {useCallback, useDebugValue, useState} = require('react');
30
30
  const {
31
31
  getFragment,
@@ -31,8 +31,8 @@ const {getQueryResourceForEnvironment} = require('../QueryResource');
31
31
  const useIsMountedRef = require('../useIsMountedRef');
32
32
  const useQueryLoader = require('../useQueryLoader');
33
33
  const useRelayEnvironment = require('../useRelayEnvironment');
34
- const readFragmentInternal = require('./readFragmentInternal_REACT_CACHE');
35
- const useFragmentInternal = require('./useFragmentInternal_REACT_CACHE');
34
+ const readFragmentInternal = require('./readFragmentInternal_EXPERIMENTAL');
35
+ const useFragmentInternal = require('./useFragmentInternal_EXPERIMENTAL');
36
36
  const invariant = require('invariant');
37
37
  const {useCallback, useContext, useReducer} = require('react');
38
38
  const {
@@ -55,16 +55,13 @@ export type RefetchFn<
55
55
  // /nullable/.
56
56
  // - Or, expects /a subset/ of the query variables if the provided key type is
57
57
  // /non-null/.
58
- // prettier-ignore
59
58
  export type RefetchFnDynamic<
60
59
  TQuery: OperationType,
61
- TKey: ?{ +$data?: mixed, ... },
60
+ TKey: ?{+$data?: mixed, ...},
62
61
  TOptions = Options,
63
- > = $Call<
64
- & (( { +$data?: mixed, ... }) => RefetchFnInexact<TQuery, TOptions>)
65
- & ((?{ +$data?: mixed, ... }) => RefetchFnExact<TQuery, TOptions>),
66
- TKey
67
- >;
62
+ > = [TKey] extends [{+$data?: mixed, ...}]
63
+ ? RefetchFnInexact<TQuery, TOptions>
64
+ : RefetchFnExact<TQuery, TOptions>;
68
65
 
69
66
  export type ReturnType<
70
67
  TQuery: OperationType,
@@ -353,6 +350,7 @@ function useRefetchableFragmentNode<
353
350
  return {
354
351
  fragmentData,
355
352
  fragmentRef,
353
+ // $FlowFixMe[incompatible-return] RefetchFn not compatible with RefetchFnDynamic
356
354
  refetch,
357
355
  };
358
356
  }
@@ -481,11 +479,13 @@ function useRefetchFunction<TQuery: OperationType>(
481
479
  const refetchQuery = createOperationDescriptor(
482
480
  refetchableRequest,
483
481
  refetchVariables,
484
- {force: true},
482
+ {
483
+ force: true,
484
+ },
485
485
  );
486
486
 
487
487
  // We call loadQuery which will start a network request if necessary
488
- // and update the querRef from useQueryLoader.
488
+ // and update the queryRef from useQueryLoader.
489
489
  // Note the following:
490
490
  // - loadQuery will dispose of any previously refetched queries.
491
491
  // - We use the variables extracted off the OperationDescriptor
@@ -15,7 +15,7 @@ import type {ReturnType} from '../useRefetchableFragment';
15
15
  import type {FragmentType, RefetchableFragment, Variables} from 'relay-runtime';
16
16
 
17
17
  const useStaticFragmentNodeWarning = require('../useStaticFragmentNodeWarning');
18
- const useRefetchableFragmentInternal = require('./useRefetchableFragmentInternal_REACT_CACHE');
18
+ const useRefetchableFragmentInternal = require('./useRefetchableFragmentInternal_EXPERIMENTAL');
19
19
  const {useDebugValue} = require('react');
20
20
  const {getFragment} = require('relay-runtime');
21
21
 
@@ -11,8 +11,8 @@
11
11
 
12
12
  'use strict';
13
13
 
14
- import type {Cache} from './LRUCache';
15
- import type {QueryResource, QueryResult} from './QueryResource';
14
+ import type {Cache} from '../LRUCache';
15
+ import type {QueryResource, QueryResult} from '../QueryResource';
16
16
  import type {
17
17
  ConcreteRequest,
18
18
  DataID,
@@ -24,9 +24,9 @@ import type {
24
24
  } from 'relay-runtime';
25
25
  import type {MissingLiveResolverField} from 'relay-runtime/store/RelayStoreTypes';
26
26
 
27
- const LRUCache = require('./LRUCache');
28
- const {getQueryResourceForEnvironment} = require('./QueryResource');
29
- const SuspenseResource = require('./SuspenseResource');
27
+ const LRUCache = require('../LRUCache');
28
+ const {getQueryResourceForEnvironment} = require('../QueryResource');
29
+ const SuspenseResource = require('../SuspenseResource');
30
30
  const invariant = require('invariant');
31
31
  const {
32
32
  __internal: {fetchQuery, getPromiseForActiveRequest},
@@ -566,6 +566,7 @@ class FragmentResourceImpl {
566
566
  this._environment,
567
567
  s.missingRequiredFields,
568
568
  s.relayResolverErrors,
569
+ s.errorResponseFields,
569
570
  );
570
571
  });
571
572
  } else {
@@ -573,6 +574,7 @@ class FragmentResourceImpl {
573
574
  this._environment,
574
575
  snapshot.missingRequiredFields,
575
576
  snapshot.relayResolverErrors,
577
+ snapshot.errorResponseFields,
576
578
  );
577
579
  }
578
580
  }
@@ -776,6 +778,7 @@ class FragmentResourceImpl {
776
778
  selector: currentSnapshot.selector,
777
779
  missingRequiredFields: currentSnapshot.missingRequiredFields,
778
780
  relayResolverErrors: currentSnapshot.relayResolverErrors,
781
+ errorResponseFields: currentSnapshot.errorResponseFields,
779
782
  };
780
783
  if (updatedData !== renderData) {
781
784
  const result = getFragmentResult(
@@ -11,9 +11,9 @@
11
11
 
12
12
  'use strict';
13
13
 
14
- import type {RefetchableFragment} from '../../relay-runtime/util/RelayRuntimeTypes';
15
- import type {LoadMoreFn, UseLoadMoreFunctionArgs} from './useLoadMoreFunction';
14
+ import type {LoadMoreFn, UseLoadMoreFunctionArgs} from '../useLoadMoreFunction';
16
15
  import type {Options} from './useRefetchableFragmentNode';
16
+ import type {RefetchableFragment} from 'relay-runtime';
17
17
  import type {
18
18
  Disposable,
19
19
  FragmentType,
@@ -22,9 +22,9 @@ import type {
22
22
  Variables,
23
23
  } from 'relay-runtime';
24
24
 
25
- const useLoadMoreFunction = require('./useLoadMoreFunction');
25
+ const useLoadMoreFunction = require('../useLoadMoreFunction');
26
+ const useStaticFragmentNodeWarning = require('../useStaticFragmentNodeWarning');
26
27
  const useRefetchableFragmentNode = require('./useRefetchableFragmentNode');
27
- const useStaticFragmentNodeWarning = require('./useStaticFragmentNodeWarning');
28
28
  const invariant = require('invariant');
29
29
  const {useCallback, useEffect, useRef, useState} = require('react');
30
30
  const {
@@ -34,15 +34,12 @@ const {
34
34
  } = require('relay-runtime');
35
35
 
36
36
  type RefetchVariables<TVariables, TKey> =
37
- // NOTE: This $Call ensures that the type of the variables is either:
37
+ // NOTE: This type ensures that the type of the variables is either:
38
38
  // - nullable if the provided ref type is non-nullable
39
39
  // - non-nullable if the provided ref type is nullable, and the caller need to provide the full set of variables
40
- // prettier-ignore
41
- $Call<
42
- & (<TFragmentType>( { +$fragmentSpreads: TFragmentType, ... }) => Partial<TVariables>)
43
- & (<TFragmentType>(?{ +$fragmentSpreads: TFragmentType, ... }) => TVariables),
44
- TKey,
45
- >;
40
+ [+key: TKey] extends [+key: {+$fragmentSpreads: mixed, ...}]
41
+ ? Partial<TVariables>
42
+ : TVariables;
46
43
 
47
44
  type RefetchFnBase<TVars, TOptions> = (
48
45
  vars: TVars,
@@ -55,15 +52,12 @@ type RefetchFn<TVariables, TKey, TOptions = Options> = RefetchFnBase<
55
52
  >;
56
53
 
57
54
  type ReturnType<TVariables, TData, TKey> = {
58
- // NOTE: This $Call ensures that the type of the returned data is either:
55
+ // NOTE: This rtpw ensures that the type of the returned data is either:
59
56
  // - nullable if the provided ref type is nullable
60
57
  // - non-nullable if the provided ref type is non-nullable
61
- // prettier-ignore
62
- data: $Call<
63
- & (<TFragmentType>( { +$fragmentSpreads: TFragmentType, ... }) => TData)
64
- & (<TFragmentType>(?{ +$fragmentSpreads: TFragmentType, ... }) => ?TData),
65
- TKey,
66
- >,
58
+ data: [+key: TKey] extends [+key: {+$fragmentSpreads: mixed, ...}]
59
+ ? TData
60
+ : ?TData,
67
61
  loadNext: LoadMoreFn<TVariables>,
68
62
  loadPrevious: LoadMoreFn<TVariables>,
69
63
  hasNext: boolean,
@@ -162,6 +156,7 @@ function useBlockingPaginationFragment<
162
156
 
163
157
  return {
164
158
  // $FlowFixMe[incompatible-cast]
159
+ // $FlowFixMe[incompatible-return]
165
160
  data: (fragmentData: TData),
166
161
  loadNext,
167
162
  loadPrevious,
@@ -13,9 +13,9 @@
13
13
 
14
14
  import type {ReaderFragment} from 'relay-runtime';
15
15
 
16
+ const useRelayEnvironment = require('../useRelayEnvironment');
17
+ const useUnsafeRef_DEPRECATED = require('../useUnsafeRef_DEPRECATED');
16
18
  const {getFragmentResourceForEnvironment} = require('./FragmentResource');
17
- const useRelayEnvironment = require('./useRelayEnvironment');
18
- const useUnsafeRef_DEPRECATED = require('./useUnsafeRef_DEPRECATED');
19
19
  const {useEffect, useState} = require('react');
20
20
  const {RelayFeatureFlags, getFragmentIdentifier} = require('relay-runtime');
21
21
  const warning = require('warning');
@@ -11,8 +11,8 @@
11
11
 
12
12
  'use strict';
13
13
 
14
- import type {RefetchableIdentifierInfo} from '../../relay-runtime/util/ReaderNode';
15
- import type {LoaderFn} from './useQueryLoader';
14
+ import type {LoaderFn} from '../useQueryLoader';
15
+ import type {RefetchableIdentifierInfo} from 'relay-runtime';
16
16
  import type {
17
17
  ConcreteRequest,
18
18
  Disposable,
@@ -26,13 +26,13 @@ import type {
26
26
  VariablesOf,
27
27
  } from 'relay-runtime';
28
28
 
29
+ const ProfilerContext = require('../ProfilerContext');
30
+ const {getQueryResourceForEnvironment} = require('../QueryResource');
31
+ const useIsMountedRef = require('../useIsMountedRef');
32
+ const useQueryLoader = require('../useQueryLoader');
33
+ const useRelayEnvironment = require('../useRelayEnvironment');
29
34
  const {getFragmentResourceForEnvironment} = require('./FragmentResource');
30
- const ProfilerContext = require('./ProfilerContext');
31
- const {getQueryResourceForEnvironment} = require('./QueryResource');
32
35
  const useFragmentNode = require('./useFragmentNode');
33
- const useIsMountedRef = require('./useIsMountedRef');
34
- const useQueryLoader = require('./useQueryLoader');
35
- const useRelayEnvironment = require('./useRelayEnvironment');
36
36
  const invariant = require('invariant');
37
37
  const {useCallback, useContext, useReducer} = require('react');
38
38
  const {
@@ -55,16 +55,13 @@ export type RefetchFn<
55
55
  // /nullable/.
56
56
  // - Or, expects /a subset/ of the query variables if the provided key type is
57
57
  // /non-null/.
58
- // prettier-ignore
59
58
  export type RefetchFnDynamic<
60
59
  TQuery: OperationType,
61
- TKey: ?{ +$data?: mixed, ... },
60
+ TKey: ?{+$data?: mixed, ...},
62
61
  TOptions = Options,
63
- > = $Call<
64
- & (( { +$data?: mixed, ... }) => RefetchFnInexact<TQuery, TOptions>)
65
- & ((?{ +$data?: mixed, ... }) => RefetchFnExact<TQuery, TOptions>),
66
- TKey
67
- >;
62
+ > = [TKey] extends [{+$data?: mixed, ...}]
63
+ ? RefetchFnInexact<TQuery, TOptions>
64
+ : RefetchFnExact<TQuery, TOptions>;
68
65
 
69
66
  export type ReturnType<
70
67
  TQuery: OperationType,
@@ -363,6 +360,7 @@ function useRefetchableFragmentNode<
363
360
  return {
364
361
  fragmentData,
365
362
  fragmentRef,
363
+ // $FlowFixMe[incompatible-return] RefetchFn not compatible with RefetchFnDynamic
366
364
  refetch,
367
365
  disableStoreUpdates,
368
366
  enableStoreUpdates,
@@ -62,7 +62,7 @@ type QueryType<T> = T extends Query<infer V, infer D, infer RR>
62
62
  variables: V,
63
63
  response: D,
64
64
  rawResponse?: $NonMaybeType<RR>,
65
- }
65
+ } // $FlowFixMe[deprecated-type]
66
66
  : $Call<<T>(PreloadableConcreteRequest<T>) => T, T>;
67
67
 
68
68
  declare function loadQuery<
@@ -14,8 +14,8 @@
14
14
  import type {Fragment, FragmentType, GraphQLTaggedNode} from 'relay-runtime';
15
15
 
16
16
  const HooksImplementation = require('./HooksImplementation');
17
+ const useFragmentNode = require('./legacy/useFragmentNode');
17
18
  const {useTrackLoadQueryInRender} = require('./loadQuery');
18
- const useFragmentNode = require('./useFragmentNode');
19
19
  const useStaticFragmentNodeWarning = require('./useStaticFragmentNodeWarning');
20
20
  const {useDebugValue} = require('react');
21
21
  const {getFragment} = require('relay-runtime');
@@ -31,17 +31,23 @@ declare function useFragment<TFragmentType: FragmentType, TData>(
31
31
  key: HasSpread<TFragmentType>,
32
32
  ): TData;
33
33
 
34
+ // if the key is nullable, return nullable value
35
+ declare function useFragment<TFragmentType: FragmentType, TData>(
36
+ fragment: Fragment<TFragmentType, TData>,
37
+ key: ?HasSpread<TFragmentType>,
38
+ ): ?TData;
39
+
34
40
  // if the key is a non-nullable array of keys, return non-nullable array
35
41
  declare function useFragment<TFragmentType: FragmentType, TData>(
36
42
  fragment: Fragment<TFragmentType, TData>,
37
43
  key: $ReadOnlyArray<HasSpread<TFragmentType>>,
38
44
  ): TData;
39
45
 
40
- // if the key is null/void, return null/void value
46
+ // if the key is a nullable array of keys, return nullable array
41
47
  declare function useFragment<TFragmentType: FragmentType, TData>(
42
48
  fragment: Fragment<TFragmentType, TData>,
43
- key: null | void,
44
- ): null | void;
49
+ key: ?$ReadOnlyArray<HasSpread<TFragmentType>>,
50
+ ): ?TData;
45
51
 
46
52
  function useFragment_LEGACY(fragment: GraphQLTaggedNode, key: mixed): mixed {
47
53
  // We need to use this hook in order to be able to track if
@@ -19,14 +19,16 @@ import type {
19
19
  OperationType,
20
20
  RenderPolicy,
21
21
  } from 'relay-runtime';
22
+ import type {ReaderFragment} from 'relay-runtime/util/ReaderNode';
22
23
 
24
+ const HooksImplementation = require('./HooksImplementation');
25
+ const useFragmentNode = require('./legacy/useFragmentNode');
23
26
  const ProfilerContext = require('./ProfilerContext');
24
27
  const {
25
28
  getQueryCacheIdentifier,
26
29
  getQueryResourceForEnvironment,
27
30
  } = require('./QueryResource');
28
31
  const useFetchTrackingRef = require('./useFetchTrackingRef');
29
- const useFragmentNode = require('./useFragmentNode');
30
32
  const useRelayEnvironment = require('./useRelayEnvironment');
31
33
  const React = require('react');
32
34
 
@@ -125,7 +127,7 @@ function useLazyLoadQueryNode<TQuery: OperationType>({
125
127
  });
126
128
 
127
129
  const {fragmentNode, fragmentRef} = preparedQueryResult;
128
- const {data} = useFragmentNode<$FlowFixMe>(
130
+ const data = useFragmentNodeImpl(
129
131
  fragmentNode,
130
132
  fragmentRef,
131
133
  componentDisplayName,
@@ -133,4 +135,18 @@ function useLazyLoadQueryNode<TQuery: OperationType>({
133
135
  return data;
134
136
  }
135
137
 
138
+ function useFragmentNodeImpl(
139
+ fragment: ReaderFragment,
140
+ key: mixed,
141
+ componentDisplayName: string,
142
+ ): mixed {
143
+ const impl = HooksImplementation.get();
144
+ if (impl && impl.useFragment__internal) {
145
+ return impl.useFragment__internal(fragment, key, componentDisplayName);
146
+ } else {
147
+ const {data} = useFragmentNode<mixed>(fragment, key, componentDisplayName);
148
+ return data;
149
+ }
150
+ }
151
+
136
152
  module.exports = useLazyLoadQueryNode;