react-relay 15.0.0 → 16.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. package/ReactRelayContext.js +1 -1
  2. package/ReactRelayQueryFetcher.js.flow +1 -5
  3. package/ReactRelayQueryRenderer.js.flow +9 -36
  4. package/ReactRelayTypes.js.flow +1 -0
  5. package/buildReactRelayContainer.js.flow +3 -1
  6. package/hooks.js +1 -1
  7. package/index.js +1 -1
  8. package/legacy.js +1 -1
  9. package/lib/ReactRelayContainerUtils.js +0 -11
  10. package/lib/ReactRelayContext.js +0 -11
  11. package/lib/ReactRelayFragmentContainer.js +6 -78
  12. package/lib/ReactRelayFragmentMockRenderer.js +0 -11
  13. package/lib/ReactRelayLocalQueryRenderer.js +0 -17
  14. package/lib/ReactRelayPaginationContainer.js +5 -208
  15. package/lib/ReactRelayQueryFetcher.js +2 -51
  16. package/lib/ReactRelayQueryRenderer.js +6 -94
  17. package/lib/ReactRelayQueryRendererContext.js +0 -11
  18. package/lib/ReactRelayRefetchContainer.js +5 -91
  19. package/lib/ReactRelayTestMocker.js +9 -85
  20. package/lib/ReactRelayTypes.js +0 -11
  21. package/lib/RelayContext.js +0 -21
  22. package/lib/assertFragmentMap.js +0 -15
  23. package/lib/buildReactRelayContainer.js +0 -19
  24. package/lib/getRootVariablesForFragments.js +0 -14
  25. package/lib/hooks.js +0 -15
  26. package/lib/index.js +0 -17
  27. package/lib/isRelayEnvironment.js +1 -18
  28. package/lib/jest-react/enqueueTask.js +0 -20
  29. package/lib/jest-react/internalAct.js +0 -38
  30. package/lib/legacy.js +0 -15
  31. package/lib/multi-actor/ActorChange.js +0 -11
  32. package/lib/multi-actor/index.js +0 -11
  33. package/lib/multi-actor/useRelayActorEnvironment.js +0 -11
  34. package/lib/relay-hooks/EntryPointContainer.react.js +0 -11
  35. package/lib/relay-hooks/EntryPointTypes.flow.js +1 -14
  36. package/lib/relay-hooks/FragmentResource.js +76 -132
  37. package/lib/relay-hooks/HooksImplementation.js +0 -11
  38. package/lib/relay-hooks/InternalLogger.js +0 -11
  39. package/lib/relay-hooks/LRUCache.js +0 -22
  40. package/lib/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js +0 -18
  41. package/lib/relay-hooks/MatchContainer.js +0 -94
  42. package/lib/relay-hooks/NestedRelayEntryPointBuilderUtils.js +9 -0
  43. package/lib/relay-hooks/ProfilerContext.js +0 -15
  44. package/lib/relay-hooks/QueryResource.js +2 -68
  45. package/lib/relay-hooks/RelayEnvironmentProvider.js +0 -11
  46. package/lib/relay-hooks/SuspenseResource.js +0 -34
  47. package/lib/relay-hooks/loadEntryPoint.js +1 -24
  48. package/lib/relay-hooks/loadQuery.js +2 -106
  49. package/lib/relay-hooks/preloadQuery_DEPRECATED.js +2 -27
  50. package/lib/relay-hooks/prepareEntryPoint_DEPRECATED.js +0 -13
  51. package/lib/relay-hooks/react-cache/RelayReactCache.js +0 -12
  52. package/lib/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js +1 -36
  53. package/lib/relay-hooks/react-cache/readFragmentInternal_REACT_CACHE.js +3 -27
  54. package/lib/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js +34 -99
  55. package/lib/relay-hooks/react-cache/useFragment_REACT_CACHE.js +0 -15
  56. package/lib/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js +0 -16
  57. package/lib/relay-hooks/react-cache/usePaginationFragment_REACT_CACHE.js +1 -23
  58. package/lib/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js +0 -29
  59. package/lib/relay-hooks/react-cache/useRefetchableFragmentInternal_REACT_CACHE.js +12 -96
  60. package/lib/relay-hooks/react-cache/useRefetchableFragment_REACT_CACHE.js +0 -14
  61. package/lib/relay-hooks/useBlockingPaginationFragment.js +0 -42
  62. package/lib/relay-hooks/useClientQuery.js +0 -18
  63. package/lib/relay-hooks/useEntryPointLoader.js +0 -69
  64. package/lib/relay-hooks/useFetchTrackingRef.js +0 -26
  65. package/lib/relay-hooks/useFragment.js +0 -17
  66. package/lib/relay-hooks/useFragmentNode.js +2 -32
  67. package/lib/relay-hooks/useIsMountedRef.js +0 -11
  68. package/lib/relay-hooks/useIsOperationNodeActive.js +0 -11
  69. package/lib/relay-hooks/useIsParentQueryActive.js +0 -11
  70. package/lib/relay-hooks/useLazyLoadQuery.js +0 -18
  71. package/lib/relay-hooks/useLazyLoadQueryNode.js +0 -35
  72. package/lib/relay-hooks/useLoadMoreFunction.js +9 -34
  73. package/lib/relay-hooks/useMemoOperationDescriptor.js +0 -11
  74. package/lib/relay-hooks/useMemoVariables.js +0 -17
  75. package/lib/relay-hooks/useMutation.js +0 -11
  76. package/lib/relay-hooks/usePaginationFragment.js +1 -26
  77. package/lib/relay-hooks/usePreloadedQuery.js +0 -27
  78. package/lib/relay-hooks/useQueryLoader.js +0 -74
  79. package/lib/relay-hooks/useRefetchableFragment.js +0 -16
  80. package/lib/relay-hooks/useRefetchableFragmentNode.js +14 -97
  81. package/lib/relay-hooks/useRelayEnvironment.js +0 -11
  82. package/lib/relay-hooks/useStaticFragmentNodeWarning.js +0 -15
  83. package/lib/relay-hooks/useSubscribeToInvalidationState.js +0 -25
  84. package/lib/relay-hooks/useSubscription.js +0 -15
  85. package/lib/relay-hooks/useUnsafeRef_DEPRECATED.js +0 -17
  86. package/package.json +2 -2
  87. package/react-relay-hooks.js +2 -2
  88. package/react-relay-hooks.min.js +2 -2
  89. package/react-relay-legacy.js +2 -2
  90. package/react-relay-legacy.min.js +2 -2
  91. package/react-relay.js +2 -2
  92. package/react-relay.min.js +2 -2
  93. package/relay-hooks/EntryPointContainer.react.js.flow +5 -0
  94. package/relay-hooks/EntryPointTypes.flow.js.flow +20 -19
  95. package/relay-hooks/FragmentResource.js.flow +114 -26
  96. package/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js.flow +4 -2
  97. package/relay-hooks/NestedRelayEntryPointBuilderUtils.js.flow +51 -0
  98. package/relay-hooks/__flowtests__/EntryPointTypes/NestedEntrypoints-flowtest.js.flow +7 -5
  99. package/relay-hooks/__flowtests__/useBlockingPaginationFragment-flowtest.js.flow +5 -0
  100. package/relay-hooks/__flowtests__/usePaginationFragment-flowtest.js.flow +5 -0
  101. package/relay-hooks/__flowtests__/useRefetchableFragment-flowtest.js.flow +2 -0
  102. package/relay-hooks/loadEntryPoint.js.flow +4 -2
  103. package/relay-hooks/loadQuery.js.flow +21 -1
  104. package/relay-hooks/prepareEntryPoint_DEPRECATED.js.flow +4 -2
  105. package/relay-hooks/react-cache/readFragmentInternal_REACT_CACHE.js.flow +2 -1
  106. package/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js.flow +28 -10
  107. package/relay-hooks/react-cache/useFragment_REACT_CACHE.js.flow +3 -9
  108. package/relay-hooks/react-cache/usePaginationFragment_REACT_CACHE.js.flow +28 -57
  109. package/relay-hooks/react-cache/useRefetchableFragmentInternal_REACT_CACHE.js.flow +19 -12
  110. package/relay-hooks/react-cache/useRefetchableFragment_REACT_CACHE.js.flow +15 -31
  111. package/relay-hooks/useBlockingPaginationFragment.js.flow +2 -4
  112. package/relay-hooks/useClientQuery.js.flow +2 -2
  113. package/relay-hooks/useFragmentNode.js.flow +2 -2
  114. package/relay-hooks/useLoadMoreFunction.js.flow +15 -9
  115. package/relay-hooks/useMutation.js.flow +26 -9
  116. package/relay-hooks/usePaginationFragment.js.flow +2 -8
  117. package/relay-hooks/useQueryLoader.js.flow +2 -8
  118. package/relay-hooks/useRefetchableFragment.js.flow +3 -2
  119. package/relay-hooks/useRefetchableFragmentNode.js.flow +28 -13
@@ -11,55 +11,39 @@
11
11
 
12
12
  'use strict';
13
13
 
14
- import type {RefetchFnDynamic} from './useRefetchableFragmentInternal_REACT_CACHE';
15
- import type {
16
- FragmentType,
17
- GraphQLTaggedNode,
18
- OperationType,
19
- } from 'relay-runtime';
14
+ import type {ReturnType} from '../useRefetchableFragment';
15
+ import type {FragmentType, RefetchableFragment, Variables} from 'relay-runtime';
20
16
 
21
17
  const useStaticFragmentNodeWarning = require('../useStaticFragmentNodeWarning');
22
18
  const useRefetchableFragmentInternal = require('./useRefetchableFragmentInternal_REACT_CACHE');
23
19
  const {useDebugValue} = require('react');
24
20
  const {getFragment} = require('relay-runtime');
25
21
 
26
- type ReturnType<TQuery: OperationType, TKey: ?{+$data?: mixed, ...}> = [
27
- // NOTE: This $Call ensures that the type of the returned data is either:
28
- // - nullable if the provided ref type is nullable
29
- // - non-nullable if the provided ref type is non-nullable
30
- // prettier-ignore
31
- $Call<
32
- & (<TFragmentData>( { +$data?: TFragmentData, ... }) => TFragmentData)
33
- & (<TFragmentData>(?{ +$data?: TFragmentData, ... }) => ?TFragmentData),
34
- TKey,
35
- >,
36
- RefetchFnDynamic<TQuery, TKey>,
37
- ];
38
-
39
22
  function useRefetchableFragment<
40
- TQuery: OperationType,
41
- TKey: ?{+$data?: mixed, +$fragmentSpreads: FragmentType, ...},
23
+ TFragmentType: FragmentType,
24
+ TVariables: Variables,
25
+ TData,
26
+ TKey: ?{+$fragmentSpreads: TFragmentType, ...},
42
27
  >(
43
- fragmentInput: GraphQLTaggedNode,
28
+ fragmentInput: RefetchableFragment<TFragmentType, TData, TVariables>,
44
29
  fragmentRef: TKey,
45
- ): ReturnType<TQuery, TKey> {
30
+ ): ReturnType<TVariables, TData, TKey> {
46
31
  const fragmentNode = getFragment(fragmentInput);
47
32
  useStaticFragmentNodeWarning(
48
33
  fragmentNode,
49
34
  'first argument of useRefetchableFragment()',
50
35
  );
51
- const {fragmentData, refetch} = useRefetchableFragmentInternal<TQuery, TKey>(
52
- fragmentNode,
53
- fragmentRef,
54
- 'useRefetchableFragment()',
55
- );
36
+ const {fragmentData, refetch} = useRefetchableFragmentInternal<
37
+ {variables: TVariables, response: TData},
38
+ {data?: TData},
39
+ >(fragmentNode, fragmentRef, 'useRefetchableFragment()');
56
40
  if (__DEV__) {
57
41
  // eslint-disable-next-line react-hooks/rules-of-hooks
58
42
  useDebugValue({fragment: fragmentNode.name, data: fragmentData});
59
43
  }
60
- /* $FlowExpectedError[prop-missing] : Exposed options is a subset of internal
61
- * options */
62
- return [fragmentData, (refetch: RefetchFnDynamic<TQuery, TKey>)];
44
+ // $FlowFixMe[incompatible-return]
45
+ // $FlowFixMe[prop-missing]
46
+ return [fragmentData, refetch];
63
47
  }
64
48
 
65
49
  module.exports = useRefetchableFragment;
@@ -39,7 +39,7 @@ type RefetchVariables<TVariables, TKey> =
39
39
  // - non-nullable if the provided ref type is nullable, and the caller need to provide the full set of variables
40
40
  // prettier-ignore
41
41
  $Call<
42
- & (<TFragmentType>( { +$fragmentSpreads: TFragmentType, ... }) => $Shape<TVariables>)
42
+ & (<TFragmentType>( { +$fragmentSpreads: TFragmentType, ... }) => Partial<TVariables>)
43
43
  & (<TFragmentType>(?{ +$fragmentSpreads: TFragmentType, ... }) => TVariables),
44
44
  TKey,
45
45
  >;
@@ -89,7 +89,6 @@ function useBlockingPaginationFragment<
89
89
 
90
90
  const {
91
91
  connectionPathInFragmentData,
92
- identifierField,
93
92
  paginationRequest,
94
93
  paginationMetadata,
95
94
  stream,
@@ -132,7 +131,6 @@ function useBlockingPaginationFragment<
132
131
  fragmentIdentifier,
133
132
  fragmentNode,
134
133
  fragmentRef,
135
- identifierField,
136
134
  paginationMetadata,
137
135
  paginationRequest,
138
136
  });
@@ -148,7 +146,6 @@ function useBlockingPaginationFragment<
148
146
  fragmentIdentifier,
149
147
  fragmentNode,
150
148
  fragmentRef,
151
- identifierField,
152
149
  paginationMetadata,
153
150
  paginationRequest,
154
151
  });
@@ -157,6 +154,7 @@ function useBlockingPaginationFragment<
157
154
  (variables: TVariables, options: void | Options) => {
158
155
  disposeFetchNext();
159
156
  disposeFetchPrevious();
157
+ // $FlowFixMe[incompatible-variance]
160
158
  return refetch(variables, {...options, __environment: undefined});
161
159
  },
162
160
  [disposeFetchNext, disposeFetchPrevious, refetch],
@@ -20,8 +20,8 @@ const useLazyLoadQuery = require('./useLazyLoadQuery');
20
20
  * These queries are consist of queries for client-only data,
21
21
  * schematized via local schema extensions and/or Relay resolvers.
22
22
  */
23
- function useClientQuery<TVariables: Variables, TData>(
24
- gqlQuery: ClientQuery<TVariables, TData>,
23
+ function useClientQuery<TVariables: Variables, TData, TRawResponse>(
24
+ gqlQuery: ClientQuery<TVariables, TData, TRawResponse>,
25
25
  variables: TVariables,
26
26
  options?: {
27
27
  UNSTABLE_renderPolicy?: RenderPolicy,
@@ -17,7 +17,7 @@ const {getFragmentResourceForEnvironment} = require('./FragmentResource');
17
17
  const useRelayEnvironment = require('./useRelayEnvironment');
18
18
  const useUnsafeRef_DEPRECATED = require('./useUnsafeRef_DEPRECATED');
19
19
  const {useEffect, useState} = require('react');
20
- const {getFragmentIdentifier} = require('relay-runtime');
20
+ const {RelayFeatureFlags, getFragmentIdentifier} = require('relay-runtime');
21
21
  const warning = require('warning');
22
22
 
23
23
  type ReturnType<TFragmentData: mixed> = {
@@ -99,7 +99,7 @@ function useFragmentNode<TFragmentData: mixed>(
99
99
  // eslint-disable-next-line react-hooks/exhaustive-deps
100
100
  }, [environment, fragmentIdentifier]);
101
101
 
102
- if (__DEV__) {
102
+ if (RelayFeatureFlags.LOG_MISSING_RECORDS_IN_PROD || __DEV__) {
103
103
  if (
104
104
  fragmentRef != null &&
105
105
  (fragmentResult.data === undefined ||
@@ -33,6 +33,7 @@ const {
33
33
  ConnectionInterface,
34
34
  createOperationDescriptor,
35
35
  getPaginationVariables,
36
+ getRefetchMetadata,
36
37
  getSelector,
37
38
  getValueAtPath,
38
39
  } = require('relay-runtime');
@@ -42,7 +43,7 @@ export type LoadMoreFn<TVariables: Variables> = (
42
43
  count: number,
43
44
  options?: {
44
45
  onComplete?: (Error | null) => void,
45
- UNSTABLE_extraVariables?: $Shape<TVariables>,
46
+ UNSTABLE_extraVariables?: Partial<TVariables>,
46
47
  },
47
48
  ) => Disposable;
48
49
 
@@ -53,7 +54,6 @@ export type UseLoadMoreFunctionArgs = {
53
54
  fragmentIdentifier: string,
54
55
  fragmentData: mixed,
55
56
  connectionPathInFragmentData: $ReadOnlyArray<string | number>,
56
- identifierField: ?string,
57
57
  paginationRequest: ConcreteRequest,
58
58
  paginationMetadata: ReaderPaginationMetadata,
59
59
  componentDisplayName: string,
@@ -76,17 +76,22 @@ function useLoadMoreFunction<TVariables: Variables>(
76
76
  componentDisplayName,
77
77
  observer,
78
78
  onReset,
79
- identifierField,
80
79
  } = args;
81
80
  const environment = useRelayEnvironment();
82
81
  const {isFetchingRef, startFetch, disposeFetch, completeFetch} =
83
82
  useFetchTrackingRef();
83
+
84
+ const {identifierInfo} = getRefetchMetadata(
85
+ fragmentNode,
86
+ componentDisplayName,
87
+ );
84
88
  const identifierValue =
85
- identifierField != null &&
89
+ identifierInfo?.identifierField != null &&
86
90
  fragmentData != null &&
87
91
  typeof fragmentData === 'object'
88
- ? fragmentData[identifierField]
92
+ ? fragmentData[identifierInfo.identifierField]
89
93
  : null;
94
+
90
95
  const isMountedRef = useIsMountedRef();
91
96
  const [mirroredEnvironment, setMirroredEnvironment] = useState(environment);
92
97
  const [mirroredFragmentIdentifier, setMirroredFragmentIdentifier] =
@@ -125,7 +130,7 @@ function useLoadMoreFunction<TVariables: Variables>(
125
130
  (
126
131
  count: number,
127
132
  options: void | {
128
- UNSTABLE_extraVariables?: $Shape<TVariables>,
133
+ UNSTABLE_extraVariables?: Partial<TVariables>,
129
134
  onComplete?: (Error | null) => void,
130
135
  },
131
136
  ) => {
@@ -201,7 +206,7 @@ function useLoadMoreFunction<TVariables: Variables>(
201
206
 
202
207
  // If the query needs an identifier value ('id' or similar) and one
203
208
  // was not explicitly provided, read it from the fragment data.
204
- if (identifierField != null) {
209
+ if (identifierInfo != null) {
205
210
  // @refetchable fragments are guaranteed to have an `id` selection
206
211
  // if the type is Node, implements Node, or is @fetchable. Double-check
207
212
  // that there actually is a value at runtime.
@@ -210,11 +215,12 @@ function useLoadMoreFunction<TVariables: Variables>(
210
215
  false,
211
216
  'Relay: Expected result to have a string ' +
212
217
  '`%s` in order to refetch, got `%s`.',
213
- identifierField,
218
+ identifierInfo.identifierField,
214
219
  identifierValue,
215
220
  );
216
221
  }
217
- paginationVariables.id = identifierValue;
222
+ paginationVariables[identifierInfo.identifierQueryVariableName] =
223
+ identifierValue;
218
224
  }
219
225
 
220
226
  const paginationQuery = createOperationDescriptor(
@@ -12,15 +12,16 @@
12
12
  'use strict';
13
13
 
14
14
  import type {
15
+ CommitMutationConfig,
15
16
  DeclarativeMutationConfig,
16
17
  Disposable,
17
- GraphQLTaggedNode,
18
18
  IEnvironment,
19
- MutationConfig,
19
+ Mutation,
20
20
  MutationParameters,
21
21
  PayloadError,
22
22
  SelectorStoreUpdater,
23
23
  UploadableMap,
24
+ Variables,
24
25
  } from 'relay-runtime';
25
26
 
26
27
  const useIsMountedRef = require('./useIsMountedRef');
@@ -50,13 +51,29 @@ export type UseMutationConfig<TMutation: MutationParameters> = {
50
51
  variables: TMutation['variables'],
51
52
  };
52
53
 
53
- function useMutation<TMutation: MutationParameters>(
54
- mutation: GraphQLTaggedNode,
54
+ type UseMutationConfigInternal<TVariables, TData, TRawResponse> = {
55
+ configs?: Array<DeclarativeMutationConfig>,
56
+ onError?: ?(error: Error) => void,
57
+ onCompleted?: ?(response: TData, errors: ?Array<PayloadError>) => void,
58
+ onNext?: ?() => void,
59
+ onUnsubscribe?: ?() => void,
60
+ optimisticResponse?: TRawResponse,
61
+ optimisticUpdater?: ?SelectorStoreUpdater<TData>,
62
+ updater?: ?SelectorStoreUpdater<TData>,
63
+ uploadables?: UploadableMap,
64
+ variables: TVariables,
65
+ };
66
+
67
+ function useMutation<TVariables: Variables, TData, TRawResponse = {...}>(
68
+ mutation: Mutation<TVariables, TData, TRawResponse>,
55
69
  commitMutationFn?: (
56
70
  environment: IEnvironment,
57
- config: MutationConfig<TMutation>,
71
+ config: CommitMutationConfig<TVariables, TData, TRawResponse>,
58
72
  ) => Disposable = defaultCommitMutation,
59
- ): [(UseMutationConfig<TMutation>) => Disposable, boolean] {
73
+ ): [
74
+ (UseMutationConfigInternal<TVariables, TData, TRawResponse>) => Disposable,
75
+ boolean,
76
+ ] {
60
77
  const environment = useRelayEnvironment();
61
78
  const isMountedRef = useIsMountedRef();
62
79
  const environmentRef = useRef(environment);
@@ -94,18 +111,18 @@ function useMutation<TMutation: MutationParameters>(
94
111
  }, [environment, isMountedRef, mutation]);
95
112
 
96
113
  const commit = useCallback(
97
- (config: UseMutationConfig<TMutation>) => {
114
+ (config: UseMutationConfigInternal<TVariables, TData, TRawResponse>) => {
98
115
  if (isMountedRef.current) {
99
116
  setMutationInFlight(true);
100
117
  }
101
118
  const disposable: Disposable = commitMutationFn(environment, {
102
119
  ...config,
103
120
  mutation,
104
- onCompleted: (response, errors) => {
121
+ onCompleted: (response: TData, errors: ?Array<PayloadError>) => {
105
122
  cleanup(disposable);
106
123
  config.onCompleted?.(response, errors);
107
124
  },
108
- onError: error => {
125
+ onError: (error: Error) => {
109
126
  cleanup(disposable);
110
127
  config.onError?.(error);
111
128
  },
@@ -62,12 +62,8 @@ function usePaginationFragment_LEGACY<
62
62
  );
63
63
  const componentDisplayName = 'usePaginationFragment()';
64
64
 
65
- const {
66
- connectionPathInFragmentData,
67
- paginationRequest,
68
- paginationMetadata,
69
- identifierField,
70
- } = getPaginationMetadata(fragmentNode, componentDisplayName);
65
+ const {connectionPathInFragmentData, paginationRequest, paginationMetadata} =
66
+ getPaginationMetadata(fragmentNode, componentDisplayName);
71
67
 
72
68
  const {fragmentData, fragmentRef, refetch} = useRefetchableFragmentNode<
73
69
  $FlowFixMe,
@@ -85,7 +81,6 @@ function usePaginationFragment_LEGACY<
85
81
  fragmentIdentifier,
86
82
  fragmentNode,
87
83
  fragmentRef,
88
- identifierField,
89
84
  paginationMetadata,
90
85
  paginationRequest,
91
86
  });
@@ -100,7 +95,6 @@ function usePaginationFragment_LEGACY<
100
95
  fragmentIdentifier,
101
96
  fragmentNode,
102
97
  fragmentRef,
103
- identifierField,
104
98
  paginationMetadata,
105
99
  paginationRequest,
106
100
  });
@@ -82,9 +82,6 @@ type UseQueryLoaderHookReturnType<
82
82
  () => void,
83
83
  ];
84
84
 
85
- type ExtractVariablesType = <T>({+variables: T, ...}) => T;
86
- type ExtractResponseType = <T>({+response: T, ...}) => T;
87
-
88
85
  declare function useQueryLoader<
89
86
  TVariables: Variables,
90
87
  TData,
@@ -109,10 +106,7 @@ declare function useQueryLoader<
109
106
  declare function useQueryLoader<TQuery: OperationType>(
110
107
  preloadableRequest: PreloadableConcreteRequest<TQuery>,
111
108
  initialQueryReference?: ?PreloadedQuery<TQuery>,
112
- ): UseQueryLoaderHookReturnType<
113
- $Call<ExtractVariablesType, TQuery>,
114
- $Call<ExtractResponseType, TQuery>,
115
- >;
109
+ ): UseQueryLoaderHookReturnType<TQuery['variables'], TQuery['response']>;
116
110
 
117
111
  function useQueryLoader<
118
112
  TVariables: Variables,
@@ -201,7 +195,7 @@ function useQueryLoader<
201
195
  }
202
196
  : options;
203
197
  if (isMountedRef.current) {
204
- const updatedQueryReference = loadQuery<QueryType>(
198
+ const updatedQueryReference = loadQuery(
205
199
  options?.__environment ?? environment,
206
200
  preloadableRequest,
207
201
  variables,
@@ -31,7 +31,7 @@ type RefetchVariables<TVariables, TKey> =
31
31
  // - non-nullable if the provided ref type is non-nullable
32
32
  // prettier-ignore
33
33
  $Call<
34
- & (<TFragmentType>( { +$fragmentSpreads: TFragmentType, ... }) => $Shape<TVariables>)
34
+ & (<TFragmentType>( { +$fragmentSpreads: TFragmentType, ... }) => Partial<TVariables>)
35
35
  & (<TFragmentType>(?{ +$fragmentSpreads: TFragmentType, ... }) => TVariables),
36
36
  TKey,
37
37
  >;
@@ -46,7 +46,7 @@ export type RefetchFn<TVariables, TKey, TOptions = Options> = RefetchFnBase<
46
46
  TOptions,
47
47
  >;
48
48
 
49
- type ReturnType<TVariables, TData, TKey> = [
49
+ export type ReturnType<TVariables, TData, TKey> = [
50
50
  // NOTE: This $Call ensures that the type of the returned data is either:
51
51
  // - nullable if the provided ref type is nullable
52
52
  // - non-nullable if the provided ref type is non-nullable
@@ -100,6 +100,7 @@ function useRefetchableFragment_LEGACY<
100
100
 
101
101
  // $FlowFixMe[incompatible-return]
102
102
  // $FlowFixMe[prop-missing]
103
+ // $FlowFixMe[incompatible-variance]
103
104
  return [fragmentData, refetch];
104
105
  }
105
106
 
@@ -11,6 +11,7 @@
11
11
 
12
12
  'use strict';
13
13
 
14
+ import type {RefetchableIdentifierInfo} from '../../relay-runtime/util/ReaderNode';
14
15
  import type {LoaderFn} from './useQueryLoader';
15
16
  import type {
16
17
  ConcreteRequest,
@@ -100,7 +101,7 @@ type RefetchFnExact<TQuery: OperationType, TOptions = Options> = RefetchFnBase<
100
101
  type RefetchFnInexact<
101
102
  TQuery: OperationType,
102
103
  TOptions = Options,
103
- > = RefetchFnBase<$Shape<VariablesOf<TQuery>>, TOptions>;
104
+ > = RefetchFnBase<Partial<VariablesOf<TQuery>>, TOptions>;
104
105
 
105
106
  type Action =
106
107
  | {
@@ -173,8 +174,10 @@ function useRefetchableFragmentNode<
173
174
  componentDisplayName: string,
174
175
  ): ReturnType<TQuery, TKey, InternalOptions> {
175
176
  const parentEnvironment = useRelayEnvironment();
176
- const {refetchableRequest, fragmentRefPathInResponse, identifierField} =
177
- getRefetchMetadata(fragmentNode, componentDisplayName);
177
+ const {refetchableRequest, fragmentRefPathInResponse} = getRefetchMetadata(
178
+ fragmentNode,
179
+ componentDisplayName,
180
+ );
178
181
  const fragmentIdentifier = getFragmentIdentifier(
179
182
  fragmentNode,
180
183
  parentFragmentRef,
@@ -214,6 +217,12 @@ function useRefetchableFragmentNode<
214
217
  >((refetchableRequest: $FlowFixMe));
215
218
 
216
219
  let fragmentRef = parentFragmentRef;
220
+
221
+ const {identifierInfo} = getRefetchMetadata(
222
+ fragmentNode,
223
+ componentDisplayName,
224
+ );
225
+
217
226
  if (shouldReset) {
218
227
  dispatch({
219
228
  type: 'reset',
@@ -239,6 +248,7 @@ function useRefetchableFragmentNode<
239
248
  debugPreviousIDAndTypename = debugFunctions.getInitialIDAndType(
240
249
  refetchQuery.request.variables,
241
250
  fragmentRefPathInResponse,
251
+ identifierInfo?.identifierQueryVariableName,
242
252
  environment,
243
253
  );
244
254
  }
@@ -345,7 +355,7 @@ function useRefetchableFragmentNode<
345
355
  fragmentIdentifier,
346
356
  fragmentNode,
347
357
  fragmentRefPathInResponse,
348
- identifierField,
358
+ identifierInfo,
349
359
  loadQuery,
350
360
  parentFragmentRef,
351
361
  refetchableRequest,
@@ -381,17 +391,17 @@ function useRefetchFunction<TQuery: OperationType>(
381
391
  fragmentIdentifier: string,
382
392
  fragmentNode: ReaderFragment,
383
393
  fragmentRefPathInResponse: $ReadOnlyArray<string | number>,
384
- identifierField: ?string,
394
+ identifierInfo: ?RefetchableIdentifierInfo,
385
395
  loadQuery: LoaderFn<TQuery>,
386
396
  parentFragmentRef: mixed,
387
397
  refetchableRequest: ConcreteRequest,
388
398
  ): RefetchFn<TQuery, InternalOptions> {
389
399
  const isMountedRef = useIsMountedRef();
390
400
  const identifierValue =
391
- identifierField != null &&
401
+ identifierInfo?.identifierField != null &&
392
402
  fragmentData != null &&
393
403
  typeof fragmentData === 'object'
394
- ? fragmentData[identifierField]
404
+ ? fragmentData[identifierInfo.identifierField]
395
405
  : null;
396
406
  return useCallback(
397
407
  (
@@ -458,8 +468,10 @@ function useRefetchFunction<TQuery: OperationType>(
458
468
  // If the query needs an identifier value ('id' or similar) and one
459
469
  // was not explicitly provided, read it from the fragment data.
460
470
  if (
461
- identifierField != null &&
462
- !providedRefetchVariables.hasOwnProperty('id')
471
+ identifierInfo != null &&
472
+ !providedRefetchVariables.hasOwnProperty(
473
+ identifierInfo.identifierQueryVariableName,
474
+ )
463
475
  ) {
464
476
  // @refetchable fragments are guaranteed to have an `id` selection
465
477
  // if the type is Node, implements Node, or is @fetchable. Double-check
@@ -469,11 +481,13 @@ function useRefetchFunction<TQuery: OperationType>(
469
481
  false,
470
482
  'Relay: Expected result to have a string ' +
471
483
  '`%s` in order to refetch, got `%s`.',
472
- identifierField,
484
+ identifierInfo.identifierField,
473
485
  identifierValue,
474
486
  );
475
487
  }
476
- (refetchVariables: $FlowFixMe).id = identifierValue;
488
+ (refetchVariables: $FlowFixMe)[
489
+ identifierInfo.identifierQueryVariableName
490
+ ] = identifierValue;
477
491
  }
478
492
 
479
493
  const refetchQuery = createOperationDescriptor(
@@ -522,10 +536,11 @@ if (__DEV__) {
522
536
  getInitialIDAndType(
523
537
  memoRefetchVariables: ?Variables,
524
538
  fragmentRefPathInResponse: $ReadOnlyArray<string | number>,
539
+ identifierQueryVariableName: ?string,
525
540
  environment: IEnvironment,
526
541
  ): ?DebugIDandTypename {
527
542
  const {Record} = require('relay-runtime');
528
- const id = memoRefetchVariables?.id;
543
+ const id = memoRefetchVariables?.[identifierQueryVariableName ?? 'id'];
529
544
  if (
530
545
  fragmentRefPathInResponse.length !== 1 ||
531
546
  fragmentRefPathInResponse[0] !== 'node' ||
@@ -535,7 +550,7 @@ if (__DEV__) {
535
550
  }
536
551
  const recordSource = environment.getStore().getSource();
537
552
  const record = recordSource.get(id);
538
- const typename = record && Record.getType(record);
553
+ const typename = record == null ? null : Record.getType(record);
539
554
  if (typename == null) {
540
555
  return null;
541
556
  }