react-relay 13.2.0 → 14.0.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 (62) hide show
  1. package/ReactRelayContext.js +1 -1
  2. package/ReactRelayFragmentContainer.js.flow +7 -4
  3. package/ReactRelayPaginationContainer.js.flow +13 -8
  4. package/ReactRelayQueryFetcher.js.flow +1 -0
  5. package/ReactRelayQueryRenderer.js.flow +6 -2
  6. package/ReactRelayRefetchContainer.js.flow +10 -3
  7. package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer.graphql.js.flow +2 -2
  8. package/__flowtests__/__generated__/ReactRelayFragmentContainerFlowtest_viewer2.graphql.js.flow +2 -2
  9. package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtestQuery.graphql.js.flow +3 -3
  10. package/__flowtests__/__generated__/ReactRelayPaginationContainerFlowtest_viewer.graphql.js.flow +3 -3
  11. package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtestQuery.graphql.js.flow +3 -3
  12. package/__flowtests__/__generated__/ReactRelayRefetchContainerFlowtest_viewer.graphql.js.flow +3 -3
  13. package/__flowtests__/__generated__/RelayModernFlowtest_badref.graphql.js.flow +2 -2
  14. package/__flowtests__/__generated__/RelayModernFlowtest_notref.graphql.js.flow +2 -2
  15. package/__flowtests__/__generated__/RelayModernFlowtest_user.graphql.js.flow +2 -2
  16. package/__flowtests__/__generated__/RelayModernFlowtest_users.graphql.js.flow +2 -2
  17. package/buildReactRelayContainer.js.flow +2 -2
  18. package/hooks.js +1 -1
  19. package/index.js +1 -1
  20. package/legacy.js +1 -1
  21. package/lib/ReactRelayQueryFetcher.js +1 -0
  22. package/lib/ReactRelayQueryRenderer.js +0 -1
  23. package/lib/readContext.js +2 -1
  24. package/lib/relay-hooks/FragmentResource.js +52 -10
  25. package/lib/relay-hooks/HooksImplementation.js +29 -0
  26. package/lib/relay-hooks/MatchContainer.js +1 -0
  27. package/lib/relay-hooks/QueryResource.js +2 -1
  28. package/lib/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js +203 -56
  29. package/lib/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js +254 -109
  30. package/lib/relay-hooks/react-cache/useFragment_REACT_CACHE.js +51 -0
  31. package/lib/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js +13 -2
  32. package/lib/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js +125 -0
  33. package/lib/relay-hooks/useFragment.js +15 -1
  34. package/lib/relay-hooks/useLazyLoadQuery.js +18 -2
  35. package/lib/relay-hooks/useMutation.js +4 -5
  36. package/lib/relay-hooks/usePreloadedQuery.js +18 -2
  37. package/package.json +2 -2
  38. package/react-relay-hooks.js +2 -2
  39. package/react-relay-hooks.min.js +2 -2
  40. package/react-relay-legacy.js +2 -2
  41. package/react-relay-legacy.min.js +2 -2
  42. package/react-relay.js +2 -2
  43. package/react-relay.min.js +2 -2
  44. package/readContext.js.flow +1 -0
  45. package/relay-hooks/FragmentResource.js.flow +55 -9
  46. package/relay-hooks/HooksImplementation.js.flow +45 -0
  47. package/relay-hooks/MatchContainer.js.flow +8 -1
  48. package/relay-hooks/QueryResource.js.flow +4 -2
  49. package/relay-hooks/__flowtests__/__generated__/useFragmentFlowtest_user.graphql.js.flow +2 -2
  50. package/relay-hooks/__flowtests__/__generated__/useFragmentFlowtest_users.graphql.js.flow +2 -2
  51. package/relay-hooks/loadQuery.js.flow +2 -1
  52. package/relay-hooks/react-cache/getQueryResultOrFetchQuery_REACT_CACHE.js.flow +245 -64
  53. package/relay-hooks/react-cache/useFragmentInternal_REACT_CACHE.js.flow +242 -99
  54. package/relay-hooks/react-cache/useFragment_REACT_CACHE.js.flow +74 -0
  55. package/relay-hooks/react-cache/useLazyLoadQuery_REACT_CACHE.js.flow +10 -4
  56. package/relay-hooks/react-cache/usePreloadedQuery_REACT_CACHE.js.flow +153 -0
  57. package/relay-hooks/useFragment.js.flow +17 -10
  58. package/relay-hooks/useLazyLoadQuery.js.flow +38 -3
  59. package/relay-hooks/useMutation.js.flow +3 -3
  60. package/relay-hooks/usePreloadedQuery.js.flow +30 -2
  61. package/relay-hooks/useRefetchableFragmentNode.js.flow +26 -11
  62. package/relay-hooks/useSubscription.js.flow +14 -8
@@ -13,8 +13,12 @@
13
13
 
14
14
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
15
15
 
16
+ var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
17
+
16
18
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
17
19
 
20
+ var SuspenseResource = require('../SuspenseResource');
21
+
18
22
  var _require = require('./RelayReactCache'),
19
23
  getCacheForType = _require.getCacheForType,
20
24
  getCacheSignal = _require.getCacheSignal;
@@ -22,19 +26,75 @@ var _require = require('./RelayReactCache'),
22
26
  var invariant = require('invariant');
23
27
 
24
28
  var _require2 = require('relay-runtime'),
29
+ RelayFeatureFlags = _require2.RelayFeatureFlags,
25
30
  fetchQueryInternal = _require2.__internal.fetchQuery;
26
31
 
27
32
  var warning = require("fbjs/lib/warning");
28
33
 
29
34
  var DEFAULT_FETCH_POLICY = 'store-or-network';
30
35
 
36
+ var QueryCache = /*#__PURE__*/function () {
37
+ function QueryCache() {
38
+ this._map = new Map();
39
+ }
40
+
41
+ var _proto = QueryCache.prototype;
42
+
43
+ _proto.get = function get(environment, key) {
44
+ var forEnv = this._map.get(environment);
45
+
46
+ if (!forEnv) {
47
+ forEnv = new Map();
48
+
49
+ this._map.set(environment, forEnv);
50
+ }
51
+
52
+ return forEnv.get(key);
53
+ };
54
+
55
+ _proto.set = function set(environment, key, value) {
56
+ var forEnv = this._map.get(environment);
57
+
58
+ if (!forEnv) {
59
+ forEnv = new Map();
60
+
61
+ this._map.set(environment, forEnv);
62
+ }
63
+
64
+ forEnv.set(key, value);
65
+ };
66
+
67
+ _proto["delete"] = function _delete(environment, key) {
68
+ var forEnv = this._map.get(environment);
69
+
70
+ if (!forEnv) {
71
+ return;
72
+ }
73
+
74
+ forEnv["delete"](key);
75
+
76
+ if (forEnv.size === 0) {
77
+ this._map["delete"](environment);
78
+ }
79
+ };
80
+
81
+ return QueryCache;
82
+ }();
83
+
31
84
  function createQueryCache() {
32
- return new Map();
85
+ return new QueryCache();
33
86
  }
34
87
 
35
- function getQueryCacheKey(operation, fetchPolicy, renderPolicy) {
36
- var cacheIdentifier = "".concat(fetchPolicy, "-").concat(renderPolicy, "-").concat(operation.request.identifier);
37
- return cacheIdentifier;
88
+ var noopOnCommit = function noopOnCommit() {
89
+ return function () {
90
+ return undefined;
91
+ };
92
+ };
93
+
94
+ var noopPromise = new Promise(function () {});
95
+
96
+ function getQueryCacheKey(operation, fetchPolicy, renderPolicy, fetchKey) {
97
+ return "".concat(fetchPolicy, "-").concat(renderPolicy, "-").concat(operation.request.identifier, "-").concat(fetchKey !== null && fetchKey !== void 0 ? fetchKey : '');
38
98
  }
39
99
 
40
100
  function constructQueryResult(operation) {
@@ -49,32 +109,103 @@ function constructQueryResult(operation) {
49
109
  };
50
110
  }
51
111
 
52
- function getQueryResultOrFetchQuery_REACT_CACHE(environment, queryOperationDescriptor) {
53
- var fetchPolicy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULT_FETCH_POLICY;
54
- var maybeRenderPolicy = arguments.length > 3 ? arguments[3] : undefined;
55
- var renderPolicy = maybeRenderPolicy !== null && maybeRenderPolicy !== void 0 ? maybeRenderPolicy : environment.UNSTABLE_getDefaultRenderPolicy();
112
+ function makeInitialCacheEntry() {
113
+ return {
114
+ status: 'pending',
115
+ promise: noopPromise,
116
+ onCommit: noopOnCommit,
117
+ suspenseResource: null
118
+ };
119
+ }
120
+
121
+ function getQueryResultOrFetchQuery_REACT_CACHE(environment, queryOperationDescriptor, options) {
122
+ var _options$fetchPolicy, _options$renderPolicy;
123
+
124
+ var fetchPolicy = (_options$fetchPolicy = options === null || options === void 0 ? void 0 : options.fetchPolicy) !== null && _options$fetchPolicy !== void 0 ? _options$fetchPolicy : DEFAULT_FETCH_POLICY;
125
+ var renderPolicy = (_options$renderPolicy = options === null || options === void 0 ? void 0 : options.renderPolicy) !== null && _options$renderPolicy !== void 0 ? _options$renderPolicy : environment.UNSTABLE_getDefaultRenderPolicy();
56
126
  var cache = getCacheForType(createQueryCache);
57
- var cacheKey = getQueryCacheKey(queryOperationDescriptor, fetchPolicy, renderPolicy);
58
- var entry = cache.get(cacheKey);
127
+ var cacheKey = getQueryCacheKey(queryOperationDescriptor, fetchPolicy, renderPolicy, options === null || options === void 0 ? void 0 : options.fetchKey);
128
+ var initialEntry = cache.get(environment, cacheKey);
59
129
 
60
- if (entry === undefined) {
61
- // Initiate a query to fetch the data if needed:
62
- entry = onCacheMiss(environment, queryOperationDescriptor, fetchPolicy, renderPolicy, function (newCacheEntry) {
63
- cache.set(cacheKey, newCacheEntry);
64
- });
65
- cache.set(cacheKey, entry); // Since this is the first time rendering, retain the query. React will
66
- // trigger the abort signal when this cache entry is no longer needed.
67
-
68
- var retention = environment.retain(queryOperationDescriptor);
69
- var abortSignal = getCacheSignal();
70
- abortSignal.addEventListener('abort', function () {
71
- retention.dispose();
72
- cache["delete"](cacheKey);
73
- }, {
74
- once: true
75
- });
130
+ function updateCache(updater) {
131
+ var currentEntry = cache.get(environment, cacheKey);
132
+
133
+ if (!currentEntry) {
134
+ currentEntry = makeInitialCacheEntry();
135
+ cache.set(environment, cacheKey, currentEntry);
136
+ } // $FlowExpectedError[prop-missing] Extra properties are passed in -- this is fine
137
+
138
+
139
+ var newStatus = updater(currentEntry); // $FlowExpectedError[cannot-spread-inexact] Flow cannot understand that this is valid...
140
+
141
+ cache.set(environment, cacheKey, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, currentEntry), newStatus)); // ... but we can because QueryCacheEntry spreads QueryCacheEntryStatus, so spreading
142
+ // a QueryCacheEntryStatus into a QueryCacheEntry will result in a valid QueryCacheEntry.
143
+ } // Initiate a query to fetch the data if needed:
144
+
145
+
146
+ if (RelayFeatureFlags.USE_REACT_CACHE_LEGACY_TIMEOUTS) {
147
+ var _entry;
148
+
149
+ if (initialEntry === undefined) {
150
+ onCacheMiss(environment, queryOperationDescriptor, fetchPolicy, renderPolicy, updateCache, options === null || options === void 0 ? void 0 : options.fetchObservable);
151
+ var createdEntry = cache.get(environment, cacheKey);
152
+ !(createdEntry !== undefined) ? process.env.NODE_ENV !== "production" ? invariant(false, 'An entry should have been created by onCacheMiss. This is a bug in Relay.') : invariant(false) : void 0;
153
+ _entry = createdEntry;
154
+ } else {
155
+ _entry = initialEntry;
156
+ }
157
+
158
+ if (!_entry.suspenseResource) {
159
+ _entry.suspenseResource = new SuspenseResource(function () {
160
+ var retention = environment.retain(queryOperationDescriptor);
161
+ return {
162
+ dispose: function dispose() {
163
+ retention.dispose();
164
+ cache["delete"](environment, cacheKey);
165
+ }
166
+ };
167
+ });
168
+ }
169
+
170
+ if (_entry.onCommit === noopOnCommit) {
171
+ _entry.onCommit = function () {
172
+ !_entry.suspenseResource ? process.env.NODE_ENV !== "production" ? invariant(false, 'SuspenseResource should have been initialized. This is a bug in Relay.') : invariant(false) : void 0;
173
+
174
+ var retention = _entry.suspenseResource.permanentRetain(environment);
175
+
176
+ return function () {
177
+ retention.dispose();
178
+ };
179
+ };
180
+ }
181
+
182
+ _entry.suspenseResource.temporaryRetain(environment);
183
+ } else {
184
+ if (initialEntry === undefined) {
185
+ // This is the behavior we eventually want: We retain the query until the
186
+ // presiding Cache component unmounts, at which point the AbortSignal
187
+ // will be triggered.
188
+ onCacheMiss(environment, queryOperationDescriptor, fetchPolicy, renderPolicy, updateCache, options === null || options === void 0 ? void 0 : options.fetchObservable); // Since this is the first time rendering, retain the query. React will
189
+ // trigger the abort signal when this cache entry is no longer needed.
190
+
191
+ var retention = environment.retain(queryOperationDescriptor);
192
+
193
+ var dispose = function dispose() {
194
+ retention.dispose();
195
+ cache["delete"](environment, cacheKey);
196
+ };
197
+
198
+ var abortSignal = getCacheSignal();
199
+ abortSignal.addEventListener('abort', dispose, {
200
+ once: true
201
+ });
202
+ }
76
203
  }
77
204
 
205
+ var entry = cache.get(environment, cacheKey); // could be a different entry now if synchronously resolved
206
+
207
+ !(entry !== undefined) ? process.env.NODE_ENV !== "production" ? invariant(false, 'An entry should have been created by onCacheMiss. This is a bug in Relay.') : invariant(false) : void 0;
208
+
78
209
  switch (entry.status) {
79
210
  case 'pending':
80
211
  throw entry.promise;
@@ -83,13 +214,13 @@ function getQueryResultOrFetchQuery_REACT_CACHE(environment, queryOperationDescr
83
214
  throw entry.error;
84
215
 
85
216
  case 'resolved':
86
- return entry.result;
217
+ return [entry.result, entry.onCommit];
87
218
  }
88
219
 
89
220
  !false ? process.env.NODE_ENV !== "production" ? invariant(false, 'switch statement should be exhaustive') : invariant(false) : void 0;
90
221
  }
91
222
 
92
- function onCacheMiss(environment, operation, fetchPolicy, renderPolicy, updateCache) {
223
+ function onCacheMiss(environment, operation, fetchPolicy, renderPolicy, updateCache, customFetchObservable) {
93
224
  // NB: Besides checking if the data is available, calling `check` will write missing
94
225
  // data to the store using any missing data handlers specified in the environment.
95
226
  var queryAvailability = environment.check(operation);
@@ -130,23 +261,35 @@ function onCacheMiss(environment, operation, fetchPolicy, renderPolicy, updateCa
130
261
  }
131
262
  }
132
263
 
133
- var promise = shouldFetch ? executeOperationAndKeepUpToDate(environment, operation, updateCache) : undefined;
264
+ if (shouldFetch) {
265
+ executeOperationAndKeepUpToDate(environment, operation, updateCache, customFetchObservable);
266
+ updateCache(function (existing) {
267
+ switch (existing.status) {
268
+ case 'resolved':
269
+ return existing;
134
270
 
135
- if (shouldRenderNow) {
136
- return {
137
- status: 'resolved',
138
- result: constructQueryResult(operation)
139
- };
271
+ case 'rejected':
272
+ return existing;
273
+
274
+ case 'pending':
275
+ return shouldRenderNow ? {
276
+ status: 'resolved',
277
+ result: constructQueryResult(operation)
278
+ } : existing;
279
+ }
280
+ });
140
281
  } else {
141
- !promise ? process.env.NODE_ENV !== "production" ? invariant(false, 'Should either fetch or render (or both), otherwise we would suspend forever.') : invariant(false) : void 0;
142
- return {
143
- status: 'pending',
144
- promise: promise
145
- };
282
+ !shouldRenderNow ? process.env.NODE_ENV !== "production" ? invariant(false, 'Should either fetch or be willing to render. This is a bug in Relay.') : invariant(false) : void 0;
283
+ updateCache(function (_existing) {
284
+ return {
285
+ status: 'resolved',
286
+ result: constructQueryResult(operation)
287
+ };
288
+ });
146
289
  }
147
290
  }
148
291
 
149
- function executeOperationAndKeepUpToDate(environment, operation, updateCache) {
292
+ function executeOperationAndKeepUpToDate(environment, operation, updateCache, customFetchObservable) {
150
293
  var resolvePromise;
151
294
  var promise = new Promise(function (r) {
152
295
  resolvePromise = r;
@@ -155,14 +298,16 @@ function executeOperationAndKeepUpToDate(environment, operation, updateCache) {
155
298
  promise.displayName = 'Relay(' + operation.request.node.operation.name + ')';
156
299
  var isFirstPayload = true; // FIXME We may still need to cancel network requests for live queries.
157
300
 
158
- var fetchObservable = fetchQueryInternal(environment, operation);
301
+ var fetchObservable = customFetchObservable !== null && customFetchObservable !== void 0 ? customFetchObservable : fetchQueryInternal(environment, operation);
159
302
  fetchObservable.subscribe({
160
303
  start: function start(subscription) {},
161
304
  error: function error(_error) {
162
305
  if (isFirstPayload) {
163
- updateCache({
164
- status: 'rejected',
165
- error: _error
306
+ updateCache(function (_existing) {
307
+ return {
308
+ status: 'rejected',
309
+ error: _error
310
+ };
166
311
  });
167
312
  } else {
168
313
  // TODO:T92030819 Remove this warning and actually throw the network error
@@ -175,23 +320,25 @@ function executeOperationAndKeepUpToDate(environment, operation, updateCache) {
175
320
  },
176
321
  next: function next(response) {
177
322
  // Stop suspending on the first payload because of streaming, defer, etc.
178
- updateCache({
179
- status: 'resolved',
180
- result: constructQueryResult(operation)
181
- });
182
- resolvePromise();
183
- isFirstPayload = false;
184
- },
185
- complete: function complete() {
186
- updateCache({
187
- status: 'resolved',
188
- result: constructQueryResult(operation)
323
+ updateCache(function (_existing) {
324
+ return {
325
+ status: 'resolved',
326
+ result: constructQueryResult(operation)
327
+ };
189
328
  });
190
329
  resolvePromise();
191
330
  isFirstPayload = false;
192
331
  }
332
+ }); // If the above subscription yields a value synchronously, then one of the updates
333
+ // above will have already happened and we'll now be in a resolved or rejected state.
334
+ // But in the usual case, we save the promise to the entry here:
335
+
336
+ updateCache(function (existing) {
337
+ return existing.status === 'pending' ? {
338
+ status: 'pending',
339
+ promise: promise
340
+ } : existing;
193
341
  });
194
- return promise;
195
342
  }
196
343
 
197
344
  module.exports = getQueryResultOrFetchQuery_REACT_CACHE;