react-relay 13.1.1 → 14.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (178) hide show
  1. package/ReactRelayContainerUtils.js.flow +0 -2
  2. package/ReactRelayContext.js +1 -1
  3. package/ReactRelayContext.js.flow +0 -2
  4. package/ReactRelayFragmentContainer.js.flow +7 -6
  5. package/ReactRelayFragmentMockRenderer.js.flow +0 -2
  6. package/ReactRelayLocalQueryRenderer.js.flow +1 -3
  7. package/ReactRelayPaginationContainer.js.flow +13 -10
  8. package/ReactRelayQueryFetcher.js.flow +10 -11
  9. package/ReactRelayQueryRenderer.js.flow +15 -16
  10. package/ReactRelayQueryRendererContext.js.flow +1 -3
  11. package/ReactRelayRefetchContainer.js.flow +10 -7
  12. package/ReactRelayTestMocker.js.flow +0 -2
  13. package/ReactRelayTypes.js.flow +6 -8
  14. package/RelayContext.js.flow +0 -2
  15. package/__flowtests__/ReactRelayFragmentContainer-flowtest.js.flow +2 -4
  16. package/__flowtests__/ReactRelayPaginationContainer-flowtest.js.flow +3 -5
  17. package/__flowtests__/ReactRelayRefetchContainer-flowtest.js.flow +3 -5
  18. package/__flowtests__/RelayModern-flowtest.js.flow +2 -4
  19. package/__flowtests__/RelayModernFlowtest_badref.graphql.js.flow +2 -4
  20. package/__flowtests__/RelayModernFlowtest_notref.graphql.js.flow +2 -4
  21. package/__flowtests__/RelayModernFlowtest_user.graphql.js.flow +2 -4
  22. package/__flowtests__/RelayModernFlowtest_users.graphql.js.flow +2 -4
  23. package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer.graphql.js.flow +2 -2
  24. package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer2.graphql.js.flow +2 -2
  25. package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtestQuery.graphql.js.flow +3 -3
  26. package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtest_viewer.graphql.js.flow +3 -3
  27. package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtestQuery.graphql.js.flow +3 -3
  28. package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtest_viewer.graphql.js.flow +3 -3
  29. package/__flowtests__/__generated__/RelayModernFlowtest_badref.graphql.js.flow +2 -2
  30. package/__flowtests__/__generated__/RelayModernFlowtest_notref.graphql.js.flow +2 -2
  31. package/__flowtests__/__generated__/RelayModernFlowtest_user.graphql.js.flow +2 -2
  32. package/__flowtests__/__generated__/RelayModernFlowtest_users.graphql.js.flow +2 -2
  33. package/assertFragmentMap.js.flow +0 -2
  34. package/buildReactRelayContainer.js.flow +2 -4
  35. package/getRootVariablesForFragments.js.flow +0 -2
  36. package/hooks.js +1 -1
  37. package/hooks.js.flow +0 -2
  38. package/index.js +1 -1
  39. package/index.js.flow +2 -2
  40. package/isRelayEnvironment.js.flow +0 -2
  41. package/jest-react/internalAct.js.flow +25 -9
  42. package/legacy.js +1 -1
  43. package/legacy.js.flow +0 -2
  44. package/lib/ReactRelayContainerUtils.js +0 -1
  45. package/lib/ReactRelayContext.js +0 -1
  46. package/lib/ReactRelayFragmentContainer.js +10 -9
  47. package/lib/ReactRelayFragmentMockRenderer.js +0 -1
  48. package/lib/ReactRelayLocalQueryRenderer.js +0 -1
  49. package/lib/ReactRelayPaginationContainer.js +14 -11
  50. package/lib/ReactRelayQueryFetcher.js +2 -2
  51. package/lib/ReactRelayQueryRenderer.js +2 -4
  52. package/lib/ReactRelayQueryRendererContext.js +0 -1
  53. package/lib/ReactRelayRefetchContainer.js +11 -14
  54. package/lib/ReactRelayTestMocker.js +1 -2
  55. package/lib/ReactRelayTypes.js +0 -1
  56. package/lib/RelayContext.js +0 -1
  57. package/lib/assertFragmentMap.js +0 -1
  58. package/lib/buildReactRelayContainer.js +1 -2
  59. package/lib/getRootVariablesForFragments.js +1 -2
  60. package/lib/hooks.js +0 -1
  61. package/lib/index.js +3 -1
  62. package/lib/isRelayEnvironment.js +0 -1
  63. package/lib/jest-react/internalAct.js +24 -4
  64. package/lib/legacy.js +0 -1
  65. package/lib/multi-actor/useRelayActorEnvironment.js +0 -1
  66. package/lib/readContext.js +2 -2
  67. package/lib/relay-hooks/EntryPointContainer.react.js +0 -1
  68. package/lib/relay-hooks/EntryPointTypes.flow.js +0 -1
  69. package/lib/relay-hooks/FragmentResource.js +68 -29
  70. package/lib/relay-hooks/HooksImplementation.js +29 -0
  71. package/lib/relay-hooks/InternalLogger.js +0 -1
  72. package/lib/relay-hooks/LRUCache.js +0 -1
  73. package/lib/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js +0 -1
  74. package/lib/relay-hooks/MatchContainer.js +2 -2
  75. package/lib/relay-hooks/ProfilerContext.js +0 -1
  76. package/lib/relay-hooks/QueryResource.js +5 -168
  77. package/lib/relay-hooks/RelayEnvironmentProvider.js +0 -1
  78. package/lib/relay-hooks/SuspenseResource.js +1 -2
  79. package/lib/relay-hooks/loadQuery.js +1 -1
  80. package/lib/relay-hooks/preloadQuery_DEPRECATED.js +8 -13
  81. package/lib/relay-hooks/prepareEntryPoint_DEPRECATED.js +0 -1
  82. package/lib/relay-hooks/react-cache/RelayReactCache.js +36 -0
  83. package/lib/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js +344 -0
  84. package/lib/relay-hooks/react-cache/readFragmentInternal_REACT_CACHE.js +239 -0
  85. package/lib/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js +598 -0
  86. package/lib/relay-hooks/react-cache/useFragment_REACT_CACHE.js +50 -0
  87. package/lib/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js +55 -0
  88. package/lib/relay-hooks/react-cache/usePaginationFragment_REACT_CACHE.js +150 -0
  89. package/lib/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js +124 -0
  90. package/lib/relay-hooks/react-cache/useRefetchableFragmentInternal_REACT_CACHE.js +367 -0
  91. package/lib/relay-hooks/react-cache/useRefetchableFragment_REACT_CACHE.js +45 -0
  92. package/lib/relay-hooks/useBlockingPaginationFragment.js +4 -3
  93. package/lib/relay-hooks/useClientQuery.js +33 -0
  94. package/lib/relay-hooks/useEntryPointLoader.js +1 -2
  95. package/lib/relay-hooks/useFetchTrackingRef.js +0 -1
  96. package/lib/relay-hooks/useFragment.js +15 -2
  97. package/lib/relay-hooks/useFragmentNode.js +0 -1
  98. package/lib/relay-hooks/useIsMountedRef.js +0 -1
  99. package/lib/relay-hooks/useLazyLoadQuery.js +4 -2
  100. package/lib/relay-hooks/useLazyLoadQueryNode.js +0 -1
  101. package/lib/relay-hooks/useLoadMoreFunction.js +1 -2
  102. package/lib/relay-hooks/useMemoOperationDescriptor.js +0 -1
  103. package/lib/relay-hooks/useMemoVariables.js +0 -1
  104. package/lib/relay-hooks/useMutation.js +5 -7
  105. package/lib/relay-hooks/usePaginationFragment.js +15 -3
  106. package/lib/relay-hooks/usePreloadedQuery.js +4 -2
  107. package/lib/relay-hooks/useQueryLoader.js +1 -2
  108. package/lib/relay-hooks/useRefetchableFragment.js +14 -2
  109. package/lib/relay-hooks/useRefetchableFragmentNode.js +1 -2
  110. package/lib/relay-hooks/useRelayEnvironment.js +0 -1
  111. package/lib/relay-hooks/useStaticFragmentNodeWarning.js +0 -1
  112. package/lib/relay-hooks/useSubscribeToInvalidationState.js +0 -1
  113. package/lib/relay-hooks/useSubscription.js +0 -1
  114. package/multi-actor/useRelayActorEnvironment.js.flow +0 -2
  115. package/package.json +3 -3
  116. package/react-relay-hooks.js +2 -2
  117. package/react-relay-hooks.min.js +2 -2
  118. package/react-relay-legacy.js +2 -2
  119. package/react-relay-legacy.min.js +2 -2
  120. package/react-relay.js +2 -2
  121. package/react-relay.min.js +2 -2
  122. package/readContext.js.flow +1 -2
  123. package/relay-hooks/EntryPointContainer.react.js.flow +2 -4
  124. package/relay-hooks/EntryPointTypes.flow.js.flow +30 -32
  125. package/relay-hooks/FragmentResource.js.flow +80 -37
  126. package/relay-hooks/HooksImplementation.js.flow +43 -0
  127. package/relay-hooks/InternalLogger.js.flow +0 -2
  128. package/relay-hooks/LRUCache.js.flow +0 -2
  129. package/relay-hooks/LazyLoadEntryPointContainer_DEPRECATED.react.js.flow +4 -6
  130. package/relay-hooks/MatchContainer.js.flow +11 -6
  131. package/relay-hooks/ProfilerContext.js.flow +0 -2
  132. package/relay-hooks/QueryResource.js.flow +12 -209
  133. package/relay-hooks/RelayEnvironmentProvider.js.flow +2 -4
  134. package/relay-hooks/SuspenseResource.js.flow +0 -2
  135. package/relay-hooks/__flowtests__/EntryPointTypes/EntryPointElementConfig-flowtest.js.flow +3 -3
  136. package/relay-hooks/__flowtests__/EntryPointTypes/NestedEntrypoints-flowtest.js.flow +2 -2
  137. package/relay-hooks/__flowtests__/__generated__/useFragmentFlowtest_user.graphql.js.flow +2 -2
  138. package/relay-hooks/__flowtests__/__generated__/useFragmentFlowtest_users.graphql.js.flow +2 -2
  139. package/relay-hooks/__flowtests__/useBlockingPaginationFragment-flowtest.js.flow +4 -6
  140. package/relay-hooks/__flowtests__/useFragment-flowtest.js.flow +0 -2
  141. package/relay-hooks/__flowtests__/usePaginationFragment-flowtest.js.flow +4 -6
  142. package/relay-hooks/__flowtests__/useRefetchableFragment-flowtest.js.flow +0 -2
  143. package/relay-hooks/__flowtests__/utils.js.flow +8 -10
  144. package/relay-hooks/loadQuery.js.flow +2 -1
  145. package/relay-hooks/preloadQuery_DEPRECATED.js.flow +11 -20
  146. package/relay-hooks/prepareEntryPoint_DEPRECATED.js.flow +0 -2
  147. package/relay-hooks/react-cache/RelayReactCache.js.flow +40 -0
  148. package/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js.flow +430 -0
  149. package/relay-hooks/react-cache/readFragmentInternal_REACT_CACHE.js.flow +297 -0
  150. package/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js.flow +599 -0
  151. package/relay-hooks/react-cache/useFragment_REACT_CACHE.js.flow +72 -0
  152. package/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js.flow +70 -0
  153. package/relay-hooks/react-cache/usePaginationFragment_REACT_CACHE.js.flow +171 -0
  154. package/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js.flow +151 -0
  155. package/relay-hooks/react-cache/useRefetchableFragmentInternal_REACT_CACHE.js.flow +595 -0
  156. package/relay-hooks/react-cache/useRefetchableFragment_REACT_CACHE.js.flow +65 -0
  157. package/relay-hooks/useBlockingPaginationFragment.js.flow +4 -6
  158. package/relay-hooks/useClientQuery.js.flow +39 -0
  159. package/relay-hooks/useEntryPointLoader.js.flow +6 -8
  160. package/relay-hooks/useFetchTrackingRef.js.flow +2 -4
  161. package/relay-hooks/useFragment.js.flow +17 -12
  162. package/relay-hooks/useFragmentNode.js.flow +2 -4
  163. package/relay-hooks/useIsMountedRef.js.flow +1 -3
  164. package/relay-hooks/useLazyLoadQuery.js.flow +17 -5
  165. package/relay-hooks/useLazyLoadQueryNode.js.flow +2 -4
  166. package/relay-hooks/useLoadMoreFunction.js.flow +6 -8
  167. package/relay-hooks/useMemoOperationDescriptor.js.flow +0 -2
  168. package/relay-hooks/useMemoVariables.js.flow +0 -2
  169. package/relay-hooks/useMutation.js.flow +5 -7
  170. package/relay-hooks/usePaginationFragment.js.flow +44 -19
  171. package/relay-hooks/usePreloadedQuery.js.flow +14 -5
  172. package/relay-hooks/useQueryLoader.js.flow +4 -6
  173. package/relay-hooks/useRefetchableFragment.js.flow +32 -3
  174. package/relay-hooks/useRefetchableFragmentNode.js.flow +38 -25
  175. package/relay-hooks/useRelayEnvironment.js.flow +0 -2
  176. package/relay-hooks/useStaticFragmentNodeWarning.js.flow +0 -2
  177. package/relay-hooks/useSubscribeToInvalidationState.js.flow +0 -2
  178. package/relay-hooks/useSubscription.js.flow +14 -10
@@ -0,0 +1,598 @@
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
+ *
8
+ * @emails oncall+relay
9
+ * @format
10
+ */
11
+ 'use strict';
12
+
13
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
14
+
15
+ var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
16
+
17
+ var _createForOfIteratorHelper2 = _interopRequireDefault(require("@babel/runtime/helpers/createForOfIteratorHelper"));
18
+
19
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
20
+
21
+ var _require = require('../QueryResource'),
22
+ getQueryResourceForEnvironment = _require.getQueryResourceForEnvironment;
23
+
24
+ var useRelayEnvironment = require('../useRelayEnvironment');
25
+
26
+ var invariant = require('invariant');
27
+
28
+ var _require2 = require('react'),
29
+ useDebugValue = _require2.useDebugValue,
30
+ useEffect = _require2.useEffect,
31
+ useMemo = _require2.useMemo,
32
+ useRef = _require2.useRef,
33
+ useState = _require2.useState;
34
+
35
+ var _require3 = require('relay-runtime'),
36
+ fetchQueryInternal = _require3.__internal.fetchQuery,
37
+ areEqualSelectors = _require3.areEqualSelectors,
38
+ createOperationDescriptor = _require3.createOperationDescriptor,
39
+ getPendingOperationsForFragment = _require3.getPendingOperationsForFragment,
40
+ getSelector = _require3.getSelector,
41
+ getVariablesFromFragment = _require3.getVariablesFromFragment,
42
+ handlePotentialSnapshotErrors = _require3.handlePotentialSnapshotErrors,
43
+ recycleNodesInto = _require3.recycleNodesInto;
44
+
45
+ var warning = require("fbjs/lib/warning");
46
+
47
+ function isMissingData(state) {
48
+ if (state.kind === 'bailout') {
49
+ return false;
50
+ } else if (state.kind === 'singular') {
51
+ return state.snapshot.isMissingData;
52
+ } else {
53
+ return state.snapshots.some(function (s) {
54
+ return s.isMissingData;
55
+ });
56
+ }
57
+ }
58
+
59
+ function getMissingClientEdges(state) {
60
+ if (state.kind === 'bailout') {
61
+ return null;
62
+ } else if (state.kind === 'singular') {
63
+ var _state$snapshot$missi;
64
+
65
+ return (_state$snapshot$missi = state.snapshot.missingClientEdges) !== null && _state$snapshot$missi !== void 0 ? _state$snapshot$missi : null;
66
+ } else {
67
+ var edges = null;
68
+
69
+ var _iterator = (0, _createForOfIteratorHelper2["default"])(state.snapshots),
70
+ _step;
71
+
72
+ try {
73
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
74
+ var snapshot = _step.value;
75
+
76
+ if (snapshot.missingClientEdges) {
77
+ var _edges;
78
+
79
+ edges = (_edges = edges) !== null && _edges !== void 0 ? _edges : [];
80
+
81
+ var _iterator2 = (0, _createForOfIteratorHelper2["default"])(snapshot.missingClientEdges),
82
+ _step2;
83
+
84
+ try {
85
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
86
+ var edge = _step2.value;
87
+ edges.push(edge);
88
+ }
89
+ } catch (err) {
90
+ _iterator2.e(err);
91
+ } finally {
92
+ _iterator2.f();
93
+ }
94
+ }
95
+ }
96
+ } catch (err) {
97
+ _iterator.e(err);
98
+ } finally {
99
+ _iterator.f();
100
+ }
101
+
102
+ return edges;
103
+ }
104
+ }
105
+
106
+ function getSuspendingLiveResolver(state) {
107
+ if (state.kind === 'bailout') {
108
+ return null;
109
+ } else if (state.kind === 'singular') {
110
+ var _state$snapshot$missi2;
111
+
112
+ return (_state$snapshot$missi2 = state.snapshot.missingLiveResolverFields) !== null && _state$snapshot$missi2 !== void 0 ? _state$snapshot$missi2 : null;
113
+ } else {
114
+ var missingFields = null;
115
+
116
+ var _iterator3 = (0, _createForOfIteratorHelper2["default"])(state.snapshots),
117
+ _step3;
118
+
119
+ try {
120
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
121
+ var snapshot = _step3.value;
122
+
123
+ if (snapshot.missingLiveResolverFields) {
124
+ var _missingFields;
125
+
126
+ missingFields = (_missingFields = missingFields) !== null && _missingFields !== void 0 ? _missingFields : [];
127
+
128
+ var _iterator4 = (0, _createForOfIteratorHelper2["default"])(snapshot.missingLiveResolverFields),
129
+ _step4;
130
+
131
+ try {
132
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
133
+ var edge = _step4.value;
134
+ missingFields.push(edge);
135
+ }
136
+ } catch (err) {
137
+ _iterator4.e(err);
138
+ } finally {
139
+ _iterator4.f();
140
+ }
141
+ }
142
+ }
143
+ } catch (err) {
144
+ _iterator3.e(err);
145
+ } finally {
146
+ _iterator3.f();
147
+ }
148
+
149
+ return missingFields;
150
+ }
151
+ }
152
+
153
+ function handlePotentialSnapshotErrorsForState(environment, state) {
154
+ if (state.kind === 'singular') {
155
+ handlePotentialSnapshotErrors(environment, state.snapshot.missingRequiredFields, state.snapshot.relayResolverErrors);
156
+ } else if (state.kind === 'plural') {
157
+ var _iterator5 = (0, _createForOfIteratorHelper2["default"])(state.snapshots),
158
+ _step5;
159
+
160
+ try {
161
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
162
+ var snapshot = _step5.value;
163
+ handlePotentialSnapshotErrors(environment, snapshot.missingRequiredFields, snapshot.relayResolverErrors);
164
+ }
165
+ } catch (err) {
166
+ _iterator5.e(err);
167
+ } finally {
168
+ _iterator5.f();
169
+ }
170
+ }
171
+ }
172
+ /**
173
+ * Check for updates to the store that occurred concurrently with rendering the given `state` value,
174
+ * returning a new (updated) state if there were updates or null if there were no changes.
175
+ */
176
+
177
+
178
+ function handleMissedUpdates(environment, state) {
179
+ if (state.kind === 'bailout') {
180
+ return null;
181
+ } // FIXME this is invalid if we've just switched environments.
182
+
183
+
184
+ var currentEpoch = environment.getStore().getEpoch();
185
+
186
+ if (currentEpoch === state.epoch) {
187
+ return null;
188
+ } // The store has updated since we rendered (without us being subscribed yet),
189
+ // so check for any updates to the data we're rendering:
190
+
191
+
192
+ if (state.kind === 'singular') {
193
+ var currentSnapshot = environment.lookup(state.snapshot.selector);
194
+ var updatedData = recycleNodesInto(state.snapshot.data, currentSnapshot.data);
195
+ var updatedCurrentSnapshot = {
196
+ data: updatedData,
197
+ isMissingData: currentSnapshot.isMissingData,
198
+ missingClientEdges: currentSnapshot.missingClientEdges,
199
+ missingLiveResolverFields: currentSnapshot.missingLiveResolverFields,
200
+ seenRecords: currentSnapshot.seenRecords,
201
+ selector: currentSnapshot.selector,
202
+ missingRequiredFields: currentSnapshot.missingRequiredFields,
203
+ relayResolverErrors: currentSnapshot.relayResolverErrors
204
+ };
205
+ return [updatedData !== state.snapshot.data, {
206
+ kind: 'singular',
207
+ snapshot: updatedCurrentSnapshot,
208
+ epoch: currentEpoch
209
+ }];
210
+ } else {
211
+ var didMissUpdates = false;
212
+ var currentSnapshots = [];
213
+
214
+ for (var index = 0; index < state.snapshots.length; index++) {
215
+ var snapshot = state.snapshots[index];
216
+
217
+ var _currentSnapshot = environment.lookup(snapshot.selector);
218
+
219
+ var _updatedData = recycleNodesInto(snapshot.data, _currentSnapshot.data);
220
+
221
+ var _updatedCurrentSnapshot = {
222
+ data: _updatedData,
223
+ isMissingData: _currentSnapshot.isMissingData,
224
+ missingClientEdges: _currentSnapshot.missingClientEdges,
225
+ missingLiveResolverFields: _currentSnapshot.missingLiveResolverFields,
226
+ seenRecords: _currentSnapshot.seenRecords,
227
+ selector: _currentSnapshot.selector,
228
+ missingRequiredFields: _currentSnapshot.missingRequiredFields,
229
+ relayResolverErrors: _currentSnapshot.relayResolverErrors
230
+ };
231
+
232
+ if (_updatedData !== snapshot.data) {
233
+ didMissUpdates = true;
234
+ }
235
+
236
+ currentSnapshots.push(_updatedCurrentSnapshot);
237
+ }
238
+
239
+ !(currentSnapshots.length === state.snapshots.length) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected same number of snapshots') : invariant(false) : void 0;
240
+ return [didMissUpdates, {
241
+ kind: 'plural',
242
+ snapshots: currentSnapshots,
243
+ epoch: currentEpoch
244
+ }];
245
+ }
246
+ }
247
+
248
+ function handleMissingClientEdge(environment, parentFragmentNode, parentFragmentRef, missingClientEdgeRequestInfo, queryOptions) {
249
+ var originalVariables = getVariablesFromFragment(parentFragmentNode, parentFragmentRef);
250
+ var variables = (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, originalVariables), {}, {
251
+ id: missingClientEdgeRequestInfo.clientEdgeDestinationID // TODO should be a reserved name
252
+
253
+ });
254
+ var queryOperationDescriptor = createOperationDescriptor(missingClientEdgeRequestInfo.request, variables, queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.networkCacheConfig); // This may suspend. We don't need to do anything with the results; all we're
255
+ // doing here is started the query if needed and retaining and releasing it
256
+ // according to the component mount/suspense cycle; QueryResource
257
+ // already handles this by itself.
258
+
259
+ var QueryResource = getQueryResourceForEnvironment(environment);
260
+ return QueryResource.prepare(queryOperationDescriptor, fetchQueryInternal(environment, queryOperationDescriptor), queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.fetchPolicy);
261
+ }
262
+
263
+ function subscribeToSnapshot(environment, state, setState) {
264
+ if (state.kind === 'bailout') {
265
+ return function () {};
266
+ } else if (state.kind === 'singular') {
267
+ var disposable = environment.subscribe(state.snapshot, function (latestSnapshot) {
268
+ setState(function (prevState) {
269
+ // In theory a setState from a subscription could be batched together
270
+ // with a setState to change the fragment selector. Guard against this
271
+ // by bailing out of the state update if the selector has changed.
272
+ if (prevState.kind !== 'singular' || prevState.snapshot.selector !== latestSnapshot.selector) {
273
+ return prevState;
274
+ }
275
+
276
+ return {
277
+ kind: 'singular',
278
+ snapshot: latestSnapshot,
279
+ epoch: environment.getStore().getEpoch()
280
+ };
281
+ });
282
+ });
283
+ return function () {
284
+ disposable.dispose();
285
+ };
286
+ } else {
287
+ var disposables = state.snapshots.map(function (snapshot, index) {
288
+ return environment.subscribe(snapshot, function (latestSnapshot) {
289
+ setState(function (prevState) {
290
+ var _prevState$snapshots$;
291
+
292
+ // In theory a setState from a subscription could be batched together
293
+ // with a setState to change the fragment selector. Guard against this
294
+ // by bailing out of the state update if the selector has changed.
295
+ if (prevState.kind !== 'plural' || ((_prevState$snapshots$ = prevState.snapshots[index]) === null || _prevState$snapshots$ === void 0 ? void 0 : _prevState$snapshots$.selector) !== latestSnapshot.selector) {
296
+ return prevState;
297
+ }
298
+
299
+ var updated = (0, _toConsumableArray2["default"])(prevState.snapshots);
300
+ updated[index] = latestSnapshot;
301
+ return {
302
+ kind: 'plural',
303
+ snapshots: updated,
304
+ epoch: environment.getStore().getEpoch()
305
+ };
306
+ });
307
+ });
308
+ });
309
+ return function () {
310
+ var _iterator6 = (0, _createForOfIteratorHelper2["default"])(disposables),
311
+ _step6;
312
+
313
+ try {
314
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
315
+ var d = _step6.value;
316
+ d.dispose();
317
+ }
318
+ } catch (err) {
319
+ _iterator6.e(err);
320
+ } finally {
321
+ _iterator6.f();
322
+ }
323
+ };
324
+ }
325
+ }
326
+
327
+ function getFragmentState(environment, fragmentSelector) {
328
+ if (fragmentSelector == null) {
329
+ return {
330
+ kind: 'bailout'
331
+ };
332
+ } else if (fragmentSelector.kind === 'PluralReaderSelector') {
333
+ // Note that if fragmentRef is an empty array, fragmentSelector will be null so we'll hit the above case.
334
+ // Null is returned by getSelector if fragmentRef has no non-null items.
335
+ return {
336
+ kind: 'plural',
337
+ snapshots: fragmentSelector.selectors.map(function (s) {
338
+ return environment.lookup(s);
339
+ }),
340
+ epoch: environment.getStore().getEpoch()
341
+ };
342
+ } else {
343
+ return {
344
+ kind: 'singular',
345
+ snapshot: environment.lookup(fragmentSelector),
346
+ epoch: environment.getStore().getEpoch()
347
+ };
348
+ }
349
+ } // fragmentNode cannot change during the lifetime of the component, though fragmentRef may change.
350
+
351
+
352
+ function useFragmentInternal_REACT_CACHE(fragmentNode, fragmentRef, hookDisplayName, queryOptions, fragmentKey) {
353
+ var _fragmentNode$metadat, _fragmentNode$metadat2;
354
+
355
+ var fragmentSelector = useMemo(function () {
356
+ return getSelector(fragmentNode, fragmentRef);
357
+ }, [fragmentNode, fragmentRef]);
358
+ var isPlural = (fragmentNode === null || fragmentNode === void 0 ? void 0 : (_fragmentNode$metadat = fragmentNode.metadata) === null || _fragmentNode$metadat === void 0 ? void 0 : _fragmentNode$metadat.plural) === true;
359
+
360
+ if (isPlural) {
361
+ !(fragmentRef == null || Array.isArray(fragmentRef)) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected fragment pointer%s for fragment `%s` to be ' + 'an array, instead got `%s`. Remove `@relay(plural: true)` ' + 'from fragment `%s` to allow the prop to be an object.', fragmentKey != null ? " for key `".concat(fragmentKey, "`") : '', fragmentNode.name, typeof fragmentRef, fragmentNode.name) : invariant(false) : void 0;
362
+ } else {
363
+ !!Array.isArray(fragmentRef) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected fragment pointer%s for fragment `%s` not to be ' + 'an array, instead got `%s`. Add `@relay(plural: true)` ' + 'to fragment `%s` to allow the prop to be an array.', fragmentKey != null ? " for key `".concat(fragmentKey, "`") : '', fragmentNode.name, typeof fragmentRef, fragmentNode.name) : invariant(false) : void 0;
364
+ }
365
+
366
+ !(fragmentRef == null || isPlural && Array.isArray(fragmentRef) && fragmentRef.length === 0 || fragmentSelector != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected to receive an object where `...%s` was spread, ' + 'but the fragment reference was not found`. This is most ' + 'likely the result of:\n' + "- Forgetting to spread `%s` in `%s`'s parent's fragment.\n" + '- Conditionally fetching `%s` but unconditionally passing %s prop ' + 'to `%s`. If the parent fragment only fetches the fragment conditionally ' + '- with e.g. `@include`, `@skip`, or inside a `... on SomeType { }` ' + 'spread - then the fragment reference will not exist. ' + 'In this case, pass `null` if the conditions for evaluating the ' + 'fragment are not met (e.g. if the `@include(if)` value is false.)', fragmentNode.name, fragmentNode.name, hookDisplayName, fragmentNode.name, fragmentKey == null ? 'a fragment reference' : "the `".concat(fragmentKey, "`"), hookDisplayName) : invariant(false) : void 0;
367
+ var environment = useRelayEnvironment();
368
+
369
+ var _useState = useState(function () {
370
+ return getFragmentState(environment, fragmentSelector);
371
+ }),
372
+ _state = _useState[0],
373
+ setState = _useState[1];
374
+
375
+ var state = _state; // This copy of the state we only update when something requires us to
376
+ // unsubscribe and re-subscribe, namely a changed environment or
377
+ // fragment selector.
378
+
379
+ var _useState2 = useState(state),
380
+ _subscribedState = _useState2[0],
381
+ setSubscribedState = _useState2[1]; // FIXME since this is used as an effect dependency, it needs to be memoized.
382
+
383
+
384
+ var subscribedState = _subscribedState;
385
+
386
+ var _useState3 = useState(fragmentSelector),
387
+ previousFragmentSelector = _useState3[0],
388
+ setPreviousFragmentSelector = _useState3[1];
389
+
390
+ var _useState4 = useState(environment),
391
+ previousEnvironment = _useState4[0],
392
+ setPreviousEnvironment = _useState4[1];
393
+
394
+ if (!areEqualSelectors(fragmentSelector, previousFragmentSelector) || environment !== previousEnvironment) {
395
+ // Enqueue setState to record the new selector and state
396
+ setPreviousFragmentSelector(fragmentSelector);
397
+ setPreviousEnvironment(environment);
398
+ var newState = getFragmentState(environment, fragmentSelector);
399
+ setState(newState);
400
+ setSubscribedState(newState); // This causes us to form a new subscription
401
+ // But render with the latest state w/o waiting for the setState. Otherwise
402
+ // the component would render the wrong information temporarily (including
403
+ // possibly incorrectly triggering some warnings below).
404
+
405
+ state = newState;
406
+ subscribedState = newState;
407
+ } // The purpose of this is to detect whether we have ever committed, because we
408
+ // don't suspend on store updates, only when the component either is first trying
409
+ // to mount or when the our selector changes. The selector change in particular is
410
+ // how we suspend for pagination and refetech. Also, fragment selector can be null
411
+ // or undefined, so we use false as a special value to distinguish from all fragment
412
+ // selectors; false means that the component hasn't mounted yet.
413
+
414
+
415
+ var committedFragmentSelectorRef = useRef(false);
416
+ useEffect(function () {
417
+ committedFragmentSelectorRef.current = fragmentSelector;
418
+ }, [fragmentSelector]); // Handle the queries for any missing client edges; this may suspend.
419
+ // FIXME handle client edges in parallel.
420
+
421
+ if (((_fragmentNode$metadat2 = fragmentNode.metadata) === null || _fragmentNode$metadat2 === void 0 ? void 0 : _fragmentNode$metadat2.hasClientEdges) === true) {
422
+ // The fragment is validated to be static (in useFragment) and hasClientEdges is
423
+ // a static (constant) property of the fragment. In practice, this effect will
424
+ // always or never run for a given invocation of this hook.
425
+ // eslint-disable-next-line react-hooks/rules-of-hooks
426
+ var clientEdgeQueries = useMemo(function () {
427
+ var missingClientEdges = getMissingClientEdges(state); // eslint-disable-next-line no-shadow
428
+
429
+ var clientEdgeQueries;
430
+
431
+ if (missingClientEdges !== null && missingClientEdges !== void 0 && missingClientEdges.length) {
432
+ clientEdgeQueries = [];
433
+
434
+ var _iterator7 = (0, _createForOfIteratorHelper2["default"])(missingClientEdges),
435
+ _step7;
436
+
437
+ try {
438
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
439
+ var edge = _step7.value;
440
+ clientEdgeQueries.push(handleMissingClientEdge(environment, fragmentNode, fragmentRef, edge, queryOptions));
441
+ }
442
+ } catch (err) {
443
+ _iterator7.e(err);
444
+ } finally {
445
+ _iterator7.f();
446
+ }
447
+ }
448
+
449
+ return clientEdgeQueries;
450
+ }, [state, environment, fragmentNode, fragmentRef, queryOptions]); // See above note
451
+ // eslint-disable-next-line react-hooks/rules-of-hooks
452
+
453
+ useEffect(function () {
454
+ var QueryResource = getQueryResourceForEnvironment(environment);
455
+
456
+ if (clientEdgeQueries !== null && clientEdgeQueries !== void 0 && clientEdgeQueries.length) {
457
+ var disposables = [];
458
+
459
+ var _iterator8 = (0, _createForOfIteratorHelper2["default"])(clientEdgeQueries),
460
+ _step8;
461
+
462
+ try {
463
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
464
+ var query = _step8.value;
465
+ disposables.push(QueryResource.retain(query));
466
+ }
467
+ } catch (err) {
468
+ _iterator8.e(err);
469
+ } finally {
470
+ _iterator8.f();
471
+ }
472
+
473
+ return function () {
474
+ var _iterator9 = (0, _createForOfIteratorHelper2["default"])(disposables),
475
+ _step9;
476
+
477
+ try {
478
+ for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
479
+ var disposable = _step9.value;
480
+ disposable.dispose();
481
+ }
482
+ } catch (err) {
483
+ _iterator9.e(err);
484
+ } finally {
485
+ _iterator9.f();
486
+ }
487
+ };
488
+ }
489
+ }, [environment, clientEdgeQueries]);
490
+ }
491
+
492
+ if (isMissingData(state)) {
493
+ // Suspend if a Live Resolver within this fragment is in a suspended state:
494
+ var suspendingLiveResolvers = getSuspendingLiveResolver(state);
495
+
496
+ if (suspendingLiveResolvers != null && suspendingLiveResolvers.length > 0) {
497
+ throw Promise.all(suspendingLiveResolvers.map(function (_ref) {
498
+ var liveStateID = _ref.liveStateID;
499
+ // $FlowFixMe[prop-missing] This is expected to be a LiveResolverStore
500
+ return environment.getStore().getLiveResolverPromise(liveStateID);
501
+ }));
502
+ } // Suspend if an active operation bears on this fragment, either the
503
+ // fragment's owner or some other mutation etc. that could affect it.
504
+ // We only suspend when the component is first trying to mount or changing
505
+ // selectors, not if data becomes missing later:
506
+
507
+
508
+ if (!committedFragmentSelectorRef.current || !areEqualSelectors(committedFragmentSelectorRef.current, fragmentSelector)) {
509
+ !(fragmentSelector != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'refinement, see invariants above') : invariant(false) : void 0;
510
+ var fragmentOwner = fragmentSelector.kind === 'PluralReaderSelector' ? fragmentSelector.selectors[0].owner : fragmentSelector.owner;
511
+ var pendingOperationsResult = getPendingOperationsForFragment(environment, fragmentNode, fragmentOwner);
512
+
513
+ if (pendingOperationsResult) {
514
+ throw pendingOperationsResult.promise;
515
+ }
516
+ } // Report required fields only if we're not suspending, since that means
517
+ // they're missing even though we are out of options for possibly fetching them:
518
+
519
+
520
+ handlePotentialSnapshotErrorsForState(environment, state);
521
+ }
522
+
523
+ useEffect(function () {
524
+ // Check for updates since the state was rendered
525
+ var currentState = subscribedState;
526
+ var updates = handleMissedUpdates(environment, subscribedState);
527
+
528
+ if (updates !== null) {
529
+ var didMissUpdates = updates[0],
530
+ updatedState = updates[1]; // TODO: didMissUpdates only checks for changes to snapshot data, but it's possible
531
+ // that other snapshot properties may have changed that should also trigger a re-render,
532
+ // such as changed missing resolver fields, missing client edges, etc.
533
+ // A potential alternative is for handleMissedUpdates() to recycle the entire state
534
+ // value, and return the new (recycled) state only if there was some change. In that
535
+ // case the code would always setState if something in the snapshot changed, in addition
536
+ // to using the latest snapshot to subscribe.
537
+
538
+ if (didMissUpdates) {
539
+ setState(updatedState);
540
+ }
541
+
542
+ currentState = updatedState;
543
+ }
544
+
545
+ return subscribeToSnapshot(environment, currentState, setState);
546
+ }, [environment, subscribedState]);
547
+ var data;
548
+
549
+ if (isPlural) {
550
+ // Plural fragments require allocating an array of the snasphot data values,
551
+ // which has to be memoized to avoid triggering downstream re-renders.
552
+ //
553
+ // Note that isPlural is a constant property of the fragment and does not change
554
+ // for a particular useFragment invocation site
555
+ var fragmentRefIsNullish = fragmentRef == null; // for less sensitive memoization
556
+ // eslint-disable-next-line react-hooks/rules-of-hooks
557
+
558
+ data = useMemo(function () {
559
+ if (state.kind === 'bailout') {
560
+ // Bailout state can happen if the fragmentRef is a plural array that is empty or has no
561
+ // non-null entries. In that case, the compatible behavior is to return [] instead of null.
562
+ return fragmentRefIsNullish ? null : [];
563
+ } else {
564
+ !(state.kind === 'plural') ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected state to be plural because fragment is plural') : invariant(false) : void 0;
565
+ return state.snapshots.map(function (s) {
566
+ return s.data;
567
+ });
568
+ }
569
+ }, [state, fragmentRefIsNullish]);
570
+ } else if (state.kind === 'bailout') {
571
+ // This case doesn't allocate a new object so it doesn't have to be memoized
572
+ data = null;
573
+ } else {
574
+ // This case doesn't allocate a new object so it doesn't have to be memoized
575
+ !(state.kind === 'singular') ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected state to be singular because fragment is singular') : invariant(false) : void 0;
576
+ data = state.snapshot.data;
577
+ }
578
+
579
+ if (process.env.NODE_ENV !== "production") {
580
+ if (fragmentRef != null && (data === undefined || Array.isArray(data) && data.length > 0 && data.every(function (d) {
581
+ return d === undefined;
582
+ }))) {
583
+ process.env.NODE_ENV !== "production" ? warning(false, 'Relay: Expected to have been able to read non-null data for ' + 'fragment `%s` declared in ' + '`%s`, since fragment reference was non-null. ' + "Make sure that that `%s`'s parent isn't " + 'holding on to and/or passing a fragment reference for data that ' + 'has been deleted.', fragmentNode.name, hookDisplayName, hookDisplayName) : void 0;
584
+ }
585
+ }
586
+
587
+ if (process.env.NODE_ENV !== "production") {
588
+ // eslint-disable-next-line react-hooks/rules-of-hooks
589
+ useDebugValue({
590
+ fragment: fragmentNode.name,
591
+ data: data
592
+ });
593
+ }
594
+
595
+ return data;
596
+ }
597
+
598
+ module.exports = useFragmentInternal_REACT_CACHE;
@@ -0,0 +1,50 @@
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
+ * @emails oncall+relay
8
+ *
9
+ * @format
10
+ */
11
+ 'use strict';
12
+
13
+ var _require = require('../loadQuery'),
14
+ useTrackLoadQueryInRender = _require.useTrackLoadQueryInRender;
15
+
16
+ var useStaticFragmentNodeWarning = require('../useStaticFragmentNodeWarning');
17
+
18
+ var useFragmentInternal = require('./useFragmentInternal_REACT_CACHE');
19
+
20
+ var _require2 = require('react'),
21
+ useDebugValue = _require2.useDebugValue;
22
+
23
+ var _require3 = require('relay-runtime'),
24
+ getFragment = _require3.getFragment;
25
+
26
+ function useFragment(fragment, key) {
27
+ // We need to use this hook in order to be able to track if
28
+ // loadQuery was called during render
29
+ useTrackLoadQueryInRender();
30
+ var fragmentNode = getFragment(fragment);
31
+
32
+ if (process.env.NODE_ENV !== "production") {
33
+ // eslint-disable-next-line react-hooks/rules-of-hooks
34
+ useStaticFragmentNodeWarning(fragmentNode, 'first argument of useFragment()');
35
+ }
36
+
37
+ var data = useFragmentInternal(fragmentNode, key, 'useFragment()');
38
+
39
+ if (process.env.NODE_ENV !== "production") {
40
+ // eslint-disable-next-line react-hooks/rules-of-hooks
41
+ useDebugValue({
42
+ fragment: fragmentNode.name,
43
+ data: data
44
+ });
45
+ }
46
+
47
+ return data;
48
+ }
49
+
50
+ module.exports = useFragment;