react-relay 16.0.0 → 16.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.
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;