@apollo/client 3.10.8 → 3.11.0-rc.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.
- package/.changeset/angry-ravens-mate.md +5 -0
- package/.changeset/angry-seals-jog.md +5 -0
- package/.changeset/chilly-dots-shake.md +5 -0
- package/.changeset/clever-bikes-admire.md +5 -0
- package/.changeset/flat-onions-guess.md +5 -0
- package/.changeset/fluffy-badgers-rush.md +5 -0
- package/.changeset/little-suits-return.md +5 -0
- package/.changeset/nasty-olives-act.md +5 -0
- package/.changeset/pink-ants-remember.md +16 -0
- package/.changeset/pre.json +24 -0
- package/.changeset/slimy-balloons-cheat.md +5 -0
- package/.changeset/slimy-berries-yawn.md +14 -0
- package/.changeset/tasty-chairs-dress.md +5 -0
- package/.changeset/thin-lies-begin.md +5 -0
- package/.changeset/unlucky-birds-press.md +5 -0
- package/.changeset/weak-ads-develop.md +5 -0
- package/CHANGELOG.md +60 -4
- package/apollo-client.cjs +501 -410
- package/apollo-client.cjs.map +1 -1
- package/apollo-client.min.cjs +1 -1
- package/core/ApolloClient.d.ts +24 -2
- package/core/ApolloClient.js +9 -8
- package/core/ApolloClient.js.map +1 -1
- package/core/ObservableQuery.js +5 -1
- package/core/ObservableQuery.js.map +1 -1
- package/core/QueryInfo.d.ts +2 -2
- package/core/QueryInfo.js.map +1 -1
- package/core/QueryManager.d.ts +1 -1
- package/core/QueryManager.js +5 -4
- package/core/QueryManager.js.map +1 -1
- package/core/core.cjs +18 -11
- package/core/core.cjs.map +1 -1
- package/core/core.cjs.native.js +18 -11
- package/core/types.d.ts +2 -2
- package/core/types.js.map +1 -1
- package/core/watchQueryOptions.d.ts +4 -0
- package/core/watchQueryOptions.js.map +1 -1
- package/dev/dev.cjs +40 -34
- package/dev/dev.cjs.map +1 -1
- package/dev/dev.cjs.native.js +40 -34
- package/errors/errors.cjs +4 -0
- package/errors/errors.cjs.map +1 -1
- package/errors/errors.cjs.native.js +4 -0
- package/errors/index.d.ts +18 -3
- package/errors/index.js +7 -2
- package/errors/index.js.map +1 -1
- package/invariantErrorCodes.js +41 -34
- package/link/core/types.d.ts +6 -4
- package/link/core/types.js.map +1 -1
- package/link/error/index.d.ts +4 -4
- package/link/error/index.js.map +1 -1
- package/link/persisted-queries/index.d.ts +3 -3
- package/link/persisted-queries/index.js.map +1 -1
- package/link/subscriptions/index.js +1 -0
- package/link/subscriptions/index.js.map +1 -1
- package/link/subscriptions/subscriptions.cjs.map +1 -1
- package/package.json +29 -29
- package/react/hooks/hooks.cjs +445 -368
- package/react/hooks/hooks.cjs.map +1 -1
- package/react/hooks/hooks.cjs.native.js +445 -368
- package/react/hooks/internal/wrapHook.d.ts +2 -0
- package/react/hooks/internal/wrapHook.js.map +1 -1
- package/react/hooks/useBackgroundQuery.d.ts +15 -1
- package/react/hooks/useBackgroundQuery.js +5 -1
- package/react/hooks/useBackgroundQuery.js.map +1 -1
- package/react/hooks/useLazyQuery.js +54 -12
- package/react/hooks/useLazyQuery.js.map +1 -1
- package/react/hooks/useLoadableQuery.d.ts +7 -1
- package/react/hooks/useLoadableQuery.js +5 -1
- package/react/hooks/useLoadableQuery.js.map +1 -1
- package/react/hooks/useQuery.d.ts +34 -47
- package/react/hooks/useQuery.js +387 -388
- package/react/hooks/useQuery.js.map +1 -1
- package/react/hooks/useQueryRefHandlers.d.ts +7 -1
- package/react/hooks/useQueryRefHandlers.js +5 -1
- package/react/hooks/useQueryRefHandlers.js.map +1 -1
- package/react/hooks/useSubscription.d.ts +13 -10
- package/react/hooks/useSubscription.js +130 -98
- package/react/hooks/useSubscription.js.map +1 -1
- package/react/hooks/useSuspenseQuery.js +3 -3
- package/react/hooks/useSuspenseQuery.js.map +1 -1
- package/react/hooks/useSyncExternalStore.js +1 -1
- package/react/internal/cache/QueryReference.js +1 -1
- package/react/internal/internal.cjs +2 -2
- package/react/internal/internal.cjs.map +1 -1
- package/react/internal/internal.cjs.native.js +2 -2
- package/react/parser/index.js +5 -5
- package/react/parser/parser.cjs +5 -5
- package/react/parser/parser.cjs.map +1 -1
- package/react/parser/parser.cjs.native.js +5 -5
- package/react/query-preloader/createQueryPreloader.js +5 -1
- package/react/query-preloader/createQueryPreloader.js.map +1 -1
- package/react/react.cjs +12 -1
- package/react/react.cjs.map +1 -1
- package/react/react.cjs.native.js +12 -1
- package/react/types/types.d.ts +19 -0
- package/react/types/types.documentation.d.ts +10 -0
- package/react/types/types.documentation.js.map +1 -1
- package/react/types/types.js.map +1 -1
- package/testing/core/core.cjs +6 -5
- package/testing/core/core.cjs.map +1 -1
- package/testing/core/core.cjs.native.js +6 -5
- package/testing/core/mocking/mockLink.js +8 -7
- package/testing/core/mocking/mockLink.js.map +1 -1
- package/testing/experimental/createSchemaFetch.d.ts +2 -0
- package/testing/experimental/createSchemaFetch.js +12 -1
- package/testing/experimental/createSchemaFetch.js.map +1 -1
- package/testing/experimental/createTestSchema.d.ts +2 -0
- package/testing/experimental/createTestSchema.js +2 -0
- package/testing/experimental/createTestSchema.js.map +1 -1
- package/testing/experimental/experimental.cjs +5 -1
- package/testing/experimental/experimental.cjs.map +1 -1
- package/testing/experimental/experimental.cjs.native.js +5 -1
- package/testing/internal/disposables/enableFakeTimers.d.ts +7 -0
- package/testing/internal/disposables/enableFakeTimers.js +16 -0
- package/testing/internal/disposables/enableFakeTimers.js.map +1 -0
- package/testing/internal/disposables/index.d.ts +1 -0
- package/testing/internal/disposables/index.js +1 -0
- package/testing/internal/disposables/index.js.map +1 -1
- package/utilities/common/errorHandling.d.ts +1 -1
- package/utilities/globals/globals.cjs +1 -1
- package/utilities/globals/globals.cjs.map +1 -1
- package/utilities/globals/globals.cjs.native.js +1 -1
- package/utilities/graphql/DocumentTransform.js +1 -1
- package/utilities/graphql/directives.js +4 -4
- package/utilities/graphql/fragments.js +3 -3
- package/utilities/graphql/getFromAST.js +8 -8
- package/utilities/graphql/storeUtils.js +1 -1
- package/utilities/graphql/transform.js +2 -2
- package/utilities/utilities.cjs +19 -19
- package/utilities/utilities.cjs.map +1 -1
- package/utilities/utilities.cjs.native.js +19 -19
- package/version.js +1 -1
package/react/hooks/useQuery.js
CHANGED
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
import { __assign, __rest } from "tslib";
|
|
2
|
+
/**
|
|
3
|
+
* Function parameters in this file try to follow a common order for the sake of
|
|
4
|
+
* readability and consistency. The order is as follows:
|
|
5
|
+
*
|
|
6
|
+
* resultData
|
|
7
|
+
* observable
|
|
8
|
+
* client
|
|
9
|
+
* query
|
|
10
|
+
* options
|
|
11
|
+
* watchQueryOptions
|
|
12
|
+
* makeWatchQueryOptions
|
|
13
|
+
* isSSRAllowed
|
|
14
|
+
* disableNetworkFetches
|
|
15
|
+
* partialRefetch
|
|
16
|
+
* renderPromises
|
|
17
|
+
* isSyncSSR
|
|
18
|
+
* callbacks
|
|
19
|
+
*/
|
|
20
|
+
/** */
|
|
2
21
|
import { invariant } from "../../utilities/globals/index.js";
|
|
3
22
|
import * as React from "rehackt";
|
|
4
23
|
import { useSyncExternalStore } from "./useSyncExternalStore.js";
|
|
@@ -9,9 +28,12 @@ import { ApolloError } from "../../errors/index.js";
|
|
|
9
28
|
import { NetworkStatus } from "../../core/index.js";
|
|
10
29
|
import { DocumentType, verifyDocumentType } from "../parser/index.js";
|
|
11
30
|
import { useApolloClient } from "./useApolloClient.js";
|
|
12
|
-
import {
|
|
31
|
+
import { compact, isNonEmptyArray, maybeDeepFreeze, } from "../../utilities/index.js";
|
|
13
32
|
import { wrapHook } from "./internal/index.js";
|
|
14
33
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
34
|
+
var originalResult = Symbol();
|
|
35
|
+
function noop() { }
|
|
36
|
+
export var lastWatchOptions = Symbol();
|
|
15
37
|
/**
|
|
16
38
|
* A hook for executing queries in an Apollo application.
|
|
17
39
|
*
|
|
@@ -51,290 +73,262 @@ export function useQuery(query, options) {
|
|
|
51
73
|
return wrapHook("useQuery", _useQuery, useApolloClient(options && options.client))(query, options);
|
|
52
74
|
}
|
|
53
75
|
function _useQuery(query, options) {
|
|
54
|
-
|
|
76
|
+
var _a = useQueryInternals(query, options), result = _a.result, obsQueryFields = _a.obsQueryFields;
|
|
77
|
+
return React.useMemo(function () { return (__assign(__assign({}, result), obsQueryFields)); }, [result, obsQueryFields]);
|
|
55
78
|
}
|
|
56
|
-
|
|
57
|
-
// By default, InternalState.prototype.forceUpdate is an empty function, but
|
|
58
|
-
// we replace it here (before anyone has had a chance to see this state yet)
|
|
59
|
-
// with a function that unconditionally forces an update, using the latest
|
|
60
|
-
// setTick function. Updating this state by calling state.forceUpdate or the
|
|
61
|
-
// uSES notification callback are the only way we trigger React component updates.
|
|
62
|
-
var forceUpdateState = React.useReducer(function (tick) { return tick + 1; }, 0)[1];
|
|
79
|
+
function useInternalState(client, query, options, renderPromises, makeWatchQueryOptions) {
|
|
63
80
|
function createInternalState(previous) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
81
|
+
var _a;
|
|
82
|
+
verifyDocumentType(query, DocumentType.Query);
|
|
83
|
+
var internalState = {
|
|
84
|
+
client: client,
|
|
85
|
+
query: query,
|
|
86
|
+
observable:
|
|
87
|
+
// See if there is an existing observable that was used to fetch the same
|
|
88
|
+
// data and if so, use it instead since it will contain the proper queryId
|
|
89
|
+
// to fetch the result set. This is used during SSR.
|
|
90
|
+
(renderPromises &&
|
|
91
|
+
renderPromises.getSSRObservable(makeWatchQueryOptions())) ||
|
|
92
|
+
client.watchQuery(getObsQueryOptions(void 0, client, options, makeWatchQueryOptions())),
|
|
93
|
+
resultData: {
|
|
94
|
+
// Reuse previousData from previous InternalState (if any) to provide
|
|
95
|
+
// continuity of previousData even if/when the query or client changes.
|
|
96
|
+
previousData: (_a = previous === null || previous === void 0 ? void 0 : previous.resultData.current) === null || _a === void 0 ? void 0 : _a.data,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
return internalState;
|
|
67
100
|
}
|
|
68
|
-
var _a = React.useState(createInternalState),
|
|
69
|
-
|
|
101
|
+
var _a = React.useState(createInternalState), internalState = _a[0], updateInternalState = _a[1];
|
|
102
|
+
/**
|
|
103
|
+
* Used by `useLazyQuery` when a new query is executed.
|
|
104
|
+
* We keep this logic here since it needs to update things in unsafe
|
|
105
|
+
* ways and here we at least can keep track of that in a single place.
|
|
106
|
+
*/
|
|
107
|
+
function onQueryExecuted(watchQueryOptions) {
|
|
108
|
+
var _a;
|
|
109
|
+
var _b;
|
|
110
|
+
// this needs to be set to prevent an immediate `resubscribe` in the
|
|
111
|
+
// next rerender of the `useQuery` internals
|
|
112
|
+
Object.assign(internalState.observable, (_a = {},
|
|
113
|
+
_a[lastWatchOptions] = watchQueryOptions,
|
|
114
|
+
_a));
|
|
115
|
+
var resultData = internalState.resultData;
|
|
116
|
+
updateInternalState(__assign(__assign({}, internalState), {
|
|
117
|
+
// might be a different query
|
|
118
|
+
query: watchQueryOptions.query, resultData: Object.assign(resultData, {
|
|
119
|
+
// We need to modify the previous `resultData` object as we rely on the
|
|
120
|
+
// object reference in other places
|
|
121
|
+
previousData: ((_b = resultData.current) === null || _b === void 0 ? void 0 : _b.data) || resultData.previousData,
|
|
122
|
+
current: undefined,
|
|
123
|
+
}) }));
|
|
124
|
+
}
|
|
125
|
+
if (client !== internalState.client || query !== internalState.query) {
|
|
70
126
|
// If the client or query have changed, we need to create a new InternalState.
|
|
71
127
|
// This will trigger a re-render with the new state, but it will also continue
|
|
72
128
|
// to run the current render function to completion.
|
|
73
129
|
// Since we sometimes trigger some side-effects in the render function, we
|
|
74
130
|
// re-assign `state` to the new state to ensure that those side-effects are
|
|
75
131
|
// triggered with the new state.
|
|
76
|
-
|
|
132
|
+
var newInternalState = createInternalState(internalState);
|
|
133
|
+
updateInternalState(newInternalState);
|
|
134
|
+
return [newInternalState, onQueryExecuted];
|
|
77
135
|
}
|
|
78
|
-
return
|
|
136
|
+
return [internalState, onQueryExecuted];
|
|
79
137
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
// continuity of previousData even if/when the query or client changes.
|
|
109
|
-
var previousResult = previous && previous.result;
|
|
110
|
-
var previousData = previousResult && previousResult.data;
|
|
111
|
-
if (previousData) {
|
|
112
|
-
this.previousData = previousData;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Forces an update using local component state.
|
|
117
|
-
* As this is not batched with `useSyncExternalStore` updates,
|
|
118
|
-
* this is only used as a fallback if the `useSyncExternalStore` "force update"
|
|
119
|
-
* method is not registered at the moment.
|
|
120
|
-
* See https://github.com/facebook/react/issues/25191
|
|
121
|
-
* */
|
|
122
|
-
InternalState.prototype.forceUpdateState = function () {
|
|
123
|
-
// Replaced (in useInternalState) with a method that triggers an update.
|
|
124
|
-
globalThis.__DEV__ !== false && invariant.warn(51);
|
|
125
|
-
};
|
|
126
|
-
InternalState.prototype.executeQuery = function (options) {
|
|
127
|
-
var _this = this;
|
|
128
|
-
var _a;
|
|
129
|
-
if (options.query) {
|
|
130
|
-
Object.assign(this, { query: options.query });
|
|
131
|
-
}
|
|
132
|
-
this.watchQueryOptions = this.createWatchQueryOptions((this.queryHookOptions = options));
|
|
133
|
-
var concast = this.observable.reobserveAsConcast(this.getObsQueryOptions());
|
|
134
|
-
// Make sure getCurrentResult returns a fresh ApolloQueryResult<TData>,
|
|
135
|
-
// but save the current data as this.previousData, just like setResult
|
|
136
|
-
// usually does.
|
|
137
|
-
this.previousData = ((_a = this.result) === null || _a === void 0 ? void 0 : _a.data) || this.previousData;
|
|
138
|
-
this.result = void 0;
|
|
139
|
-
this.forceUpdate();
|
|
140
|
-
return new Promise(function (resolve) {
|
|
141
|
-
var result;
|
|
142
|
-
// Subscribe to the concast independently of the ObservableQuery in case
|
|
143
|
-
// the component gets unmounted before the promise resolves. This prevents
|
|
144
|
-
// the concast from terminating early and resolving with `undefined` when
|
|
145
|
-
// there are no more subscribers for the concast.
|
|
146
|
-
concast.subscribe({
|
|
147
|
-
next: function (value) {
|
|
148
|
-
result = value;
|
|
149
|
-
},
|
|
150
|
-
error: function () {
|
|
151
|
-
resolve(_this.toQueryResult(_this.observable.getCurrentResult()));
|
|
152
|
-
},
|
|
153
|
-
complete: function () {
|
|
154
|
-
resolve(_this.toQueryResult(result));
|
|
155
|
-
},
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
};
|
|
159
|
-
// Methods beginning with use- should be called according to the standard
|
|
160
|
-
// rules of React hooks: only at the top level of the calling function, and
|
|
161
|
-
// without any dynamic conditional logic.
|
|
162
|
-
InternalState.prototype.useQuery = function (options) {
|
|
163
|
-
var _this = this;
|
|
164
|
-
// The renderPromises field gets initialized here in the useQuery method, at
|
|
165
|
-
// the beginning of everything (for a given component rendering, at least),
|
|
166
|
-
// so we can safely use this.renderPromises in other/later InternalState
|
|
167
|
-
// methods without worrying it might be uninitialized. Even after
|
|
168
|
-
// initialization, this.renderPromises is usually undefined (unless SSR is
|
|
169
|
-
// happening), but that's fine as long as it has been initialized that way,
|
|
170
|
-
// rather than left uninitialized.
|
|
171
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
172
|
-
this.renderPromises = React.useContext(getApolloContext()).renderPromises;
|
|
173
|
-
this.useOptions(options);
|
|
174
|
-
var obsQuery = this.useObservableQuery();
|
|
175
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
176
|
-
var result = useSyncExternalStore(
|
|
177
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
178
|
-
React.useCallback(function (handleStoreChange) {
|
|
179
|
-
if (_this.renderPromises) {
|
|
180
|
-
return function () { };
|
|
181
|
-
}
|
|
182
|
-
_this.forceUpdate = handleStoreChange;
|
|
183
|
-
var onNext = function () {
|
|
184
|
-
var previousResult = _this.result;
|
|
185
|
-
// We use `getCurrentResult()` instead of the onNext argument because
|
|
186
|
-
// the values differ slightly. Specifically, loading results will have
|
|
187
|
-
// an empty object for data instead of `undefined` for some reason.
|
|
188
|
-
var result = obsQuery.getCurrentResult();
|
|
189
|
-
// Make sure we're not attempting to re-render similar results
|
|
190
|
-
if (previousResult &&
|
|
191
|
-
previousResult.loading === result.loading &&
|
|
192
|
-
previousResult.networkStatus === result.networkStatus &&
|
|
193
|
-
equal(previousResult.data, result.data)) {
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
_this.setResult(result);
|
|
197
|
-
};
|
|
198
|
-
var onError = function (error) {
|
|
199
|
-
subscription.unsubscribe();
|
|
200
|
-
subscription = obsQuery.resubscribeAfterError(onNext, onError);
|
|
201
|
-
if (!hasOwnProperty.call(error, "graphQLErrors")) {
|
|
202
|
-
// The error is not a GraphQL error
|
|
203
|
-
throw error;
|
|
204
|
-
}
|
|
205
|
-
var previousResult = _this.result;
|
|
206
|
-
if (!previousResult ||
|
|
207
|
-
(previousResult && previousResult.loading) ||
|
|
208
|
-
!equal(error, previousResult.error)) {
|
|
209
|
-
_this.setResult({
|
|
210
|
-
data: (previousResult && previousResult.data),
|
|
211
|
-
error: error,
|
|
212
|
-
loading: false,
|
|
213
|
-
networkStatus: NetworkStatus.error,
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
};
|
|
217
|
-
var subscription = obsQuery.subscribe(onNext, onError);
|
|
218
|
-
// Do the "unsubscribe" with a short delay.
|
|
219
|
-
// This way, an existing subscription can be reused without an additional
|
|
220
|
-
// request if "unsubscribe" and "resubscribe" to the same ObservableQuery
|
|
221
|
-
// happen in very fast succession.
|
|
222
|
-
return function () {
|
|
223
|
-
setTimeout(function () { return subscription.unsubscribe(); });
|
|
224
|
-
_this.forceUpdate = function () { return _this.forceUpdateState(); };
|
|
225
|
-
};
|
|
226
|
-
}, [
|
|
227
|
-
// We memoize the subscribe function using useCallback and the following
|
|
228
|
-
// dependency keys, because the subscribe function reference is all that
|
|
229
|
-
// useSyncExternalStore uses internally as a dependency key for the
|
|
230
|
-
// useEffect ultimately responsible for the subscription, so we are
|
|
231
|
-
// effectively passing this dependency array to that useEffect buried
|
|
232
|
-
// inside useSyncExternalStore, as desired.
|
|
233
|
-
obsQuery,
|
|
234
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
235
|
-
this.renderPromises,
|
|
236
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
237
|
-
this.client.disableNetworkFetches,
|
|
238
|
-
]), function () { return _this.getCurrentResult(); }, function () { return _this.getCurrentResult(); });
|
|
239
|
-
// TODO Remove this method when we remove support for options.partialRefetch.
|
|
240
|
-
this.unsafeHandlePartialRefetch(result);
|
|
241
|
-
return this.toQueryResult(result);
|
|
138
|
+
export function useQueryInternals(query, options) {
|
|
139
|
+
var client = useApolloClient(options.client);
|
|
140
|
+
var renderPromises = React.useContext(getApolloContext()).renderPromises;
|
|
141
|
+
var isSyncSSR = !!renderPromises;
|
|
142
|
+
var disableNetworkFetches = client.disableNetworkFetches;
|
|
143
|
+
var ssrAllowed = options.ssr !== false && !options.skip;
|
|
144
|
+
var partialRefetch = options.partialRefetch;
|
|
145
|
+
var makeWatchQueryOptions = createMakeWatchQueryOptions(client, query, options, isSyncSSR);
|
|
146
|
+
var _a = useInternalState(client, query, options, renderPromises, makeWatchQueryOptions), _b = _a[0], observable = _b.observable, resultData = _b.resultData, onQueryExecuted = _a[1];
|
|
147
|
+
var watchQueryOptions = makeWatchQueryOptions(observable);
|
|
148
|
+
useResubscribeIfNecessary(resultData, // might get mutated during render
|
|
149
|
+
observable, // might get mutated during render
|
|
150
|
+
client, options, watchQueryOptions);
|
|
151
|
+
var obsQueryFields = React.useMemo(function () { return bindObservableMethods(observable); }, [observable]);
|
|
152
|
+
useHandleSkip(resultData, // might get mutated during render
|
|
153
|
+
observable, client, options, watchQueryOptions, disableNetworkFetches, isSyncSSR);
|
|
154
|
+
useRegisterSSRObservable(observable, renderPromises, ssrAllowed);
|
|
155
|
+
var result = useObservableSubscriptionResult(resultData, observable, client, disableNetworkFetches, partialRefetch, isSyncSSR, {
|
|
156
|
+
onCompleted: options.onCompleted || noop,
|
|
157
|
+
onError: options.onError || noop,
|
|
158
|
+
});
|
|
159
|
+
return {
|
|
160
|
+
result: result,
|
|
161
|
+
obsQueryFields: obsQueryFields,
|
|
162
|
+
observable: observable,
|
|
163
|
+
resultData: resultData,
|
|
164
|
+
client: client,
|
|
165
|
+
onQueryExecuted: onQueryExecuted,
|
|
242
166
|
};
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
// allows us to depend on the referential stability of
|
|
248
|
-
// this.watchQueryOptions elsewhere.
|
|
249
|
-
var currentWatchQueryOptions = this.watchQueryOptions;
|
|
250
|
-
if (!equal(watchQueryOptions, currentWatchQueryOptions)) {
|
|
251
|
-
this.watchQueryOptions = watchQueryOptions;
|
|
252
|
-
if (currentWatchQueryOptions && this.observable) {
|
|
253
|
-
// Though it might be tempting to postpone this reobserve call to the
|
|
254
|
-
// useEffect block, we need getCurrentResult to return an appropriate
|
|
255
|
-
// loading:true result synchronously (later within the same call to
|
|
256
|
-
// useQuery). Since we already have this.observable here (not true for
|
|
257
|
-
// the very first call to useQuery), we are not initiating any new
|
|
258
|
-
// subscriptions, though it does feel less than ideal that reobserve
|
|
259
|
-
// (potentially) kicks off a network request (for example, when the
|
|
260
|
-
// variables have changed), which is technically a side-effect.
|
|
261
|
-
this.observable.reobserve(this.getObsQueryOptions());
|
|
262
|
-
// Make sure getCurrentResult returns a fresh ApolloQueryResult<TData>,
|
|
263
|
-
// but save the current data as this.previousData, just like setResult
|
|
264
|
-
// usually does.
|
|
265
|
-
this.previousData = ((_a = this.result) === null || _a === void 0 ? void 0 : _a.data) || this.previousData;
|
|
266
|
-
this.result = void 0;
|
|
267
|
-
}
|
|
268
|
-
}
|
|
167
|
+
}
|
|
168
|
+
function useObservableSubscriptionResult(resultData, observable, client, disableNetworkFetches, partialRefetch, skipSubscribing, callbacks) {
|
|
169
|
+
var callbackRef = React.useRef(callbacks);
|
|
170
|
+
React.useEffect(function () {
|
|
269
171
|
// Make sure state.onCompleted and state.onError always reflect the latest
|
|
270
172
|
// options.onCompleted and options.onError callbacks provided to useQuery,
|
|
271
173
|
// since those functions are often recreated every time useQuery is called.
|
|
272
174
|
// Like the forceUpdate method, the versions of these methods inherited from
|
|
273
175
|
// InternalState.prototype are empty no-ops, but we can override them on the
|
|
274
176
|
// base state object (without modifying the prototype).
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
this.result = this.ssrDisabledResult;
|
|
284
|
-
}
|
|
285
|
-
else if (this.queryHookOptions.skip ||
|
|
286
|
-
this.watchQueryOptions.fetchPolicy === "standby") {
|
|
287
|
-
// When skipping a query (ie. we're not querying for data but still want to
|
|
288
|
-
// render children), make sure the `data` is cleared out and `loading` is
|
|
289
|
-
// set to `false` (since we aren't loading anything).
|
|
290
|
-
//
|
|
291
|
-
// NOTE: We no longer think this is the correct behavior. Skipping should
|
|
292
|
-
// not automatically set `data` to `undefined`, but instead leave the
|
|
293
|
-
// previous data in place. In other words, skipping should not mandate that
|
|
294
|
-
// previously received data is all of a sudden removed. Unfortunately,
|
|
295
|
-
// changing this is breaking, so we'll have to wait until Apollo Client 4.0
|
|
296
|
-
// to address this.
|
|
297
|
-
this.result = this.skipStandbyResult;
|
|
177
|
+
callbackRef.current = callbacks;
|
|
178
|
+
});
|
|
179
|
+
return useSyncExternalStore(React.useCallback(function (handleStoreChange) {
|
|
180
|
+
// reference `disableNetworkFetches` here to ensure that the rules of hooks
|
|
181
|
+
// keep it as a dependency of this effect, even though it's not used
|
|
182
|
+
disableNetworkFetches;
|
|
183
|
+
if (skipSubscribing) {
|
|
184
|
+
return function () { };
|
|
298
185
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
186
|
+
var onNext = function () {
|
|
187
|
+
var previousResult = resultData.current;
|
|
188
|
+
// We use `getCurrentResult()` instead of the onNext argument because
|
|
189
|
+
// the values differ slightly. Specifically, loading results will have
|
|
190
|
+
// an empty object for data instead of `undefined` for some reason.
|
|
191
|
+
var result = observable.getCurrentResult();
|
|
192
|
+
// Make sure we're not attempting to re-render similar results
|
|
193
|
+
if (previousResult &&
|
|
194
|
+
previousResult.loading === result.loading &&
|
|
195
|
+
previousResult.networkStatus === result.networkStatus &&
|
|
196
|
+
equal(previousResult.data, result.data)) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
setResult(result, resultData, observable, client, partialRefetch, handleStoreChange, callbackRef.current);
|
|
200
|
+
};
|
|
201
|
+
var onError = function (error) {
|
|
202
|
+
subscription.current.unsubscribe();
|
|
203
|
+
subscription.current = observable.resubscribeAfterError(onNext, onError);
|
|
204
|
+
if (!hasOwnProperty.call(error, "graphQLErrors")) {
|
|
205
|
+
// The error is not a GraphQL error
|
|
206
|
+
throw error;
|
|
207
|
+
}
|
|
208
|
+
var previousResult = resultData.current;
|
|
209
|
+
if (!previousResult ||
|
|
210
|
+
(previousResult && previousResult.loading) ||
|
|
211
|
+
!equal(error, previousResult.error)) {
|
|
212
|
+
setResult({
|
|
213
|
+
data: (previousResult && previousResult.data),
|
|
214
|
+
error: error,
|
|
215
|
+
loading: false,
|
|
216
|
+
networkStatus: NetworkStatus.error,
|
|
217
|
+
}, resultData, observable, client, partialRefetch, handleStoreChange, callbackRef.current);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
// TODO evaluate if we keep this in
|
|
221
|
+
// React Compiler cannot handle scoped `let` access, but a mutable object
|
|
222
|
+
// like this is fine.
|
|
223
|
+
// was:
|
|
224
|
+
// let subscription = observable.subscribe(onNext, onError);
|
|
225
|
+
var subscription = { current: observable.subscribe(onNext, onError) };
|
|
226
|
+
// Do the "unsubscribe" with a short delay.
|
|
227
|
+
// This way, an existing subscription can be reused without an additional
|
|
228
|
+
// request if "unsubscribe" and "resubscribe" to the same ObservableQuery
|
|
229
|
+
// happen in very fast succession.
|
|
230
|
+
return function () {
|
|
231
|
+
setTimeout(function () { return subscription.current.unsubscribe(); });
|
|
232
|
+
};
|
|
233
|
+
}, [
|
|
234
|
+
disableNetworkFetches,
|
|
235
|
+
skipSubscribing,
|
|
236
|
+
observable,
|
|
237
|
+
resultData,
|
|
238
|
+
partialRefetch,
|
|
239
|
+
client,
|
|
240
|
+
]), function () {
|
|
241
|
+
return getCurrentResult(resultData, observable, callbackRef.current, partialRefetch, client);
|
|
242
|
+
}, function () {
|
|
243
|
+
return getCurrentResult(resultData, observable, callbackRef.current, partialRefetch, client);
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
function useRegisterSSRObservable(observable, renderPromises, ssrAllowed) {
|
|
247
|
+
if (renderPromises && ssrAllowed) {
|
|
248
|
+
renderPromises.registerSSRObservable(observable);
|
|
249
|
+
if (observable.getCurrentResult().loading) {
|
|
250
|
+
// TODO: This is a legacy API which could probably be cleaned up
|
|
251
|
+
renderPromises.addObservableQueryPromise(observable);
|
|
311
252
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
//
|
|
321
|
-
//
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
//
|
|
331
|
-
//
|
|
332
|
-
//
|
|
333
|
-
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function useHandleSkip(
|
|
256
|
+
/** this hook will mutate properties on `resultData` */
|
|
257
|
+
resultData, observable, client, options, watchQueryOptions, disableNetworkFetches, isSyncSSR) {
|
|
258
|
+
if ((isSyncSSR || disableNetworkFetches) &&
|
|
259
|
+
options.ssr === false &&
|
|
260
|
+
!options.skip) {
|
|
261
|
+
// If SSR has been explicitly disabled, and this function has been called
|
|
262
|
+
// on the server side, return the default loading state.
|
|
263
|
+
resultData.current = toQueryResult(ssrDisabledResult, resultData.previousData, observable, client);
|
|
264
|
+
}
|
|
265
|
+
else if (options.skip || watchQueryOptions.fetchPolicy === "standby") {
|
|
266
|
+
// When skipping a query (ie. we're not querying for data but still want to
|
|
267
|
+
// render children), make sure the `data` is cleared out and `loading` is
|
|
268
|
+
// set to `false` (since we aren't loading anything).
|
|
269
|
+
//
|
|
270
|
+
// NOTE: We no longer think this is the correct behavior. Skipping should
|
|
271
|
+
// not automatically set `data` to `undefined`, but instead leave the
|
|
272
|
+
// previous data in place. In other words, skipping should not mandate that
|
|
273
|
+
// previously received data is all of a sudden removed. Unfortunately,
|
|
274
|
+
// changing this is breaking, so we'll have to wait until Apollo Client 4.0
|
|
275
|
+
// to address this.
|
|
276
|
+
resultData.current = toQueryResult(skipStandbyResult, resultData.previousData, observable, client);
|
|
277
|
+
}
|
|
278
|
+
else if (
|
|
279
|
+
// reset result if the last render was skipping for some reason,
|
|
280
|
+
// but this render isn't skipping anymore
|
|
281
|
+
resultData.current &&
|
|
282
|
+
(resultData.current[originalResult] === ssrDisabledResult ||
|
|
283
|
+
resultData.current[originalResult] === skipStandbyResult)) {
|
|
284
|
+
resultData.current = void 0;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
// this hook is not compatible with any rules of React, and there's no good way to rewrite it.
|
|
288
|
+
// it should stay a separate hook that will not be optimized by the compiler
|
|
289
|
+
function useResubscribeIfNecessary(
|
|
290
|
+
/** this hook will mutate properties on `resultData` */
|
|
291
|
+
resultData,
|
|
292
|
+
/** this hook will mutate properties on `observable` */
|
|
293
|
+
observable, client, options, watchQueryOptions) {
|
|
294
|
+
var _a;
|
|
295
|
+
if (observable[lastWatchOptions] &&
|
|
296
|
+
!equal(observable[lastWatchOptions], watchQueryOptions)) {
|
|
297
|
+
// Though it might be tempting to postpone this reobserve call to the
|
|
298
|
+
// useEffect block, we need getCurrentResult to return an appropriate
|
|
299
|
+
// loading:true result synchronously (later within the same call to
|
|
300
|
+
// useQuery). Since we already have this.observable here (not true for
|
|
301
|
+
// the very first call to useQuery), we are not initiating any new
|
|
302
|
+
// subscriptions, though it does feel less than ideal that reobserve
|
|
303
|
+
// (potentially) kicks off a network request (for example, when the
|
|
304
|
+
// variables have changed), which is technically a side-effect.
|
|
305
|
+
observable.reobserve(getObsQueryOptions(observable, client, options, watchQueryOptions));
|
|
306
|
+
// Make sure getCurrentResult returns a fresh ApolloQueryResult<TData>,
|
|
307
|
+
// but save the current data as this.previousData, just like setResult
|
|
308
|
+
// usually does.
|
|
309
|
+
resultData.previousData =
|
|
310
|
+
((_a = resultData.current) === null || _a === void 0 ? void 0 : _a.data) || resultData.previousData;
|
|
311
|
+
resultData.current = void 0;
|
|
312
|
+
}
|
|
313
|
+
observable[lastWatchOptions] = watchQueryOptions;
|
|
314
|
+
}
|
|
315
|
+
/*
|
|
316
|
+
* A function to massage options before passing them to ObservableQuery.
|
|
317
|
+
* This is two-step curried because we want to reuse the `make` function,
|
|
318
|
+
* but the `observable` might differ between calls to `make`.
|
|
319
|
+
*/
|
|
320
|
+
export function createMakeWatchQueryOptions(client, query, _a, isSyncSSR) {
|
|
321
|
+
if (_a === void 0) { _a = {}; }
|
|
322
|
+
var skip = _a.skip, ssr = _a.ssr, onCompleted = _a.onCompleted, onError = _a.onError, defaultOptions = _a.defaultOptions,
|
|
323
|
+
// The above options are useQuery-specific, so this ...otherOptions spread
|
|
324
|
+
// makes otherOptions almost a WatchQueryOptions object, except for the
|
|
325
|
+
// query property that we add below.
|
|
326
|
+
otherOptions = __rest(_a, ["skip", "ssr", "onCompleted", "onError", "defaultOptions"]);
|
|
327
|
+
return function (observable) {
|
|
334
328
|
// This Object.assign is safe because otherOptions is a fresh ...rest object
|
|
335
329
|
// that did not exist until just now, so modifications are still allowed.
|
|
336
|
-
var watchQueryOptions = Object.assign(otherOptions, { query:
|
|
337
|
-
if (
|
|
330
|
+
var watchQueryOptions = Object.assign(otherOptions, { query: query });
|
|
331
|
+
if (isSyncSSR &&
|
|
338
332
|
(watchQueryOptions.fetchPolicy === "network-only" ||
|
|
339
333
|
watchQueryOptions.fetchPolicy === "cache-and-network")) {
|
|
340
334
|
// this behavior was added to react-apollo without explanation in this PR
|
|
@@ -345,141 +339,146 @@ var InternalState = /** @class */ (function () {
|
|
|
345
339
|
watchQueryOptions.variables = {};
|
|
346
340
|
}
|
|
347
341
|
if (skip) {
|
|
348
|
-
var _c = watchQueryOptions.fetchPolicy, fetchPolicy = _c === void 0 ? this.getDefaultFetchPolicy() : _c, _d = watchQueryOptions.initialFetchPolicy, initialFetchPolicy = _d === void 0 ? fetchPolicy : _d;
|
|
349
342
|
// When skipping, we set watchQueryOptions.fetchPolicy initially to
|
|
350
343
|
// "standby", but we also need/want to preserve the initial non-standby
|
|
351
344
|
// fetchPolicy that would have been used if not skipping.
|
|
352
|
-
|
|
353
|
-
initialFetchPolicy
|
|
354
|
-
|
|
355
|
-
|
|
345
|
+
watchQueryOptions.initialFetchPolicy =
|
|
346
|
+
watchQueryOptions.initialFetchPolicy ||
|
|
347
|
+
watchQueryOptions.fetchPolicy ||
|
|
348
|
+
getDefaultFetchPolicy(defaultOptions, client.defaultOptions);
|
|
349
|
+
watchQueryOptions.fetchPolicy = "standby";
|
|
356
350
|
}
|
|
357
351
|
else if (!watchQueryOptions.fetchPolicy) {
|
|
358
352
|
watchQueryOptions.fetchPolicy =
|
|
359
|
-
(
|
|
360
|
-
|
|
353
|
+
(observable === null || observable === void 0 ? void 0 : observable.options.initialFetchPolicy) ||
|
|
354
|
+
getDefaultFetchPolicy(defaultOptions, client.defaultOptions);
|
|
361
355
|
}
|
|
362
356
|
return watchQueryOptions;
|
|
363
357
|
};
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
358
|
+
}
|
|
359
|
+
export function getObsQueryOptions(observable, client, queryHookOptions, watchQueryOptions) {
|
|
360
|
+
var toMerge = [];
|
|
361
|
+
var globalDefaults = client.defaultOptions.watchQuery;
|
|
362
|
+
if (globalDefaults)
|
|
363
|
+
toMerge.push(globalDefaults);
|
|
364
|
+
if (queryHookOptions.defaultOptions) {
|
|
365
|
+
toMerge.push(queryHookOptions.defaultOptions);
|
|
366
|
+
}
|
|
367
|
+
// We use compact rather than mergeOptions for this part of the merge,
|
|
368
|
+
// because we want watchQueryOptions.variables (if defined) to replace
|
|
369
|
+
// this.observable.options.variables whole. This replacement allows
|
|
370
|
+
// removing variables by removing them from the variables input to
|
|
371
|
+
// useQuery. If the variables were always merged together (rather than
|
|
372
|
+
// replaced), there would be no way to remove existing variables.
|
|
373
|
+
// However, the variables from options.defaultOptions and globalDefaults
|
|
374
|
+
// (if provided) should be merged, to ensure individual defaulted
|
|
375
|
+
// variables always have values, if not otherwise defined in
|
|
376
|
+
// observable.options or watchQueryOptions.
|
|
377
|
+
toMerge.push(compact(observable && observable.options, watchQueryOptions));
|
|
378
|
+
return toMerge.reduce(mergeOptions);
|
|
379
|
+
}
|
|
380
|
+
function setResult(nextResult, resultData, observable, client, partialRefetch, forceUpdate, callbacks) {
|
|
381
|
+
var previousResult = resultData.current;
|
|
382
|
+
if (previousResult && previousResult.data) {
|
|
383
|
+
resultData.previousData = previousResult.data;
|
|
384
|
+
}
|
|
385
|
+
resultData.current = toQueryResult(unsafeHandlePartialRefetch(nextResult, observable, partialRefetch), resultData.previousData, observable, client);
|
|
386
|
+
// Calling state.setResult always triggers an update, though some call sites
|
|
387
|
+
// perform additional equality checks before committing to an update.
|
|
388
|
+
forceUpdate();
|
|
389
|
+
handleErrorOrCompleted(nextResult, previousResult === null || previousResult === void 0 ? void 0 : previousResult[originalResult], callbacks);
|
|
390
|
+
}
|
|
391
|
+
function handleErrorOrCompleted(result, previousResult, callbacks) {
|
|
392
|
+
if (!result.loading) {
|
|
393
|
+
var error_1 = toApolloError(result);
|
|
394
|
+
// wait a tick in case we are in the middle of rendering a component
|
|
395
|
+
Promise.resolve()
|
|
396
|
+
.then(function () {
|
|
397
|
+
if (error_1) {
|
|
398
|
+
callbacks.onError(error_1);
|
|
400
399
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
if (!result.loading) {
|
|
418
|
-
var error_1 = this.toApolloError(result);
|
|
419
|
-
// wait a tick in case we are in the middle of rendering a component
|
|
420
|
-
Promise.resolve()
|
|
421
|
-
.then(function () {
|
|
422
|
-
if (error_1) {
|
|
423
|
-
_this.onError(error_1);
|
|
424
|
-
}
|
|
425
|
-
else if (result.data &&
|
|
426
|
-
(previousResult === null || previousResult === void 0 ? void 0 : previousResult.networkStatus) !== result.networkStatus &&
|
|
427
|
-
result.networkStatus === NetworkStatus.ready) {
|
|
428
|
-
_this.onCompleted(result.data);
|
|
429
|
-
}
|
|
430
|
-
})
|
|
431
|
-
.catch(function (error) {
|
|
432
|
-
globalThis.__DEV__ !== false && invariant.warn(error);
|
|
433
|
-
});
|
|
434
|
-
}
|
|
435
|
-
};
|
|
436
|
-
InternalState.prototype.toApolloError = function (result) {
|
|
437
|
-
return isNonEmptyArray(result.errors) ?
|
|
438
|
-
new ApolloError({ graphQLErrors: result.errors })
|
|
439
|
-
: result.error;
|
|
440
|
-
};
|
|
441
|
-
InternalState.prototype.getCurrentResult = function () {
|
|
442
|
-
// Using this.result as a cache ensures getCurrentResult continues returning
|
|
443
|
-
// the same (===) result object, unless state.setResult has been called, or
|
|
444
|
-
// we're doing server rendering and therefore override the result below.
|
|
445
|
-
if (!this.result) {
|
|
446
|
-
this.handleErrorOrCompleted((this.result = this.observable.getCurrentResult()));
|
|
447
|
-
}
|
|
448
|
-
return this.result;
|
|
449
|
-
};
|
|
450
|
-
InternalState.prototype.toQueryResult = function (result) {
|
|
451
|
-
var queryResult = this.toQueryResultCache.get(result);
|
|
452
|
-
if (queryResult)
|
|
453
|
-
return queryResult;
|
|
454
|
-
var data = result.data, partial = result.partial, resultWithoutPartial = __rest(result, ["data", "partial"]);
|
|
455
|
-
this.toQueryResultCache.set(result, (queryResult = __assign(__assign(__assign({ data: data }, resultWithoutPartial), this.obsQueryFields), { client: this.client, observable: this.observable, variables: this.observable.variables, called: !this.queryHookOptions.skip, previousData: this.previousData })));
|
|
456
|
-
if (!queryResult.error && isNonEmptyArray(result.errors)) {
|
|
457
|
-
// Until a set naming convention for networkError and graphQLErrors is
|
|
458
|
-
// decided upon, we map errors (graphQLErrors) to the error options.
|
|
459
|
-
// TODO: Is it possible for both result.error and result.errors to be
|
|
460
|
-
// defined here?
|
|
461
|
-
queryResult.error = new ApolloError({ graphQLErrors: result.errors });
|
|
462
|
-
}
|
|
463
|
-
return queryResult;
|
|
464
|
-
};
|
|
465
|
-
InternalState.prototype.unsafeHandlePartialRefetch = function (result) {
|
|
400
|
+
else if (result.data &&
|
|
401
|
+
(previousResult === null || previousResult === void 0 ? void 0 : previousResult.networkStatus) !== result.networkStatus &&
|
|
402
|
+
result.networkStatus === NetworkStatus.ready) {
|
|
403
|
+
callbacks.onCompleted(result.data);
|
|
404
|
+
}
|
|
405
|
+
})
|
|
406
|
+
.catch(function (error) {
|
|
407
|
+
globalThis.__DEV__ !== false && invariant.warn(error);
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
function getCurrentResult(resultData, observable, callbacks, partialRefetch, client) {
|
|
412
|
+
// Using this.result as a cache ensures getCurrentResult continues returning
|
|
413
|
+
// the same (===) result object, unless state.setResult has been called, or
|
|
414
|
+
// we're doing server rendering and therefore override the result below.
|
|
415
|
+
if (!resultData.current) {
|
|
466
416
|
// WARNING: SIDE-EFFECTS IN THE RENDER FUNCTION
|
|
467
|
-
//
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
417
|
+
// this could call unsafeHandlePartialRefetch
|
|
418
|
+
setResult(observable.getCurrentResult(), resultData, observable, client, partialRefetch, function () { }, callbacks);
|
|
419
|
+
}
|
|
420
|
+
return resultData.current;
|
|
421
|
+
}
|
|
422
|
+
export function getDefaultFetchPolicy(queryHookDefaultOptions, clientDefaultOptions) {
|
|
423
|
+
var _a;
|
|
424
|
+
return ((queryHookDefaultOptions === null || queryHookDefaultOptions === void 0 ? void 0 : queryHookDefaultOptions.fetchPolicy) ||
|
|
425
|
+
((_a = clientDefaultOptions === null || clientDefaultOptions === void 0 ? void 0 : clientDefaultOptions.watchQuery) === null || _a === void 0 ? void 0 : _a.fetchPolicy) ||
|
|
426
|
+
"cache-first");
|
|
427
|
+
}
|
|
428
|
+
export function toApolloError(result) {
|
|
429
|
+
return isNonEmptyArray(result.errors) ?
|
|
430
|
+
new ApolloError({ graphQLErrors: result.errors })
|
|
431
|
+
: result.error;
|
|
432
|
+
}
|
|
433
|
+
export function toQueryResult(result, previousData, observable, client) {
|
|
434
|
+
var data = result.data, partial = result.partial, resultWithoutPartial = __rest(result, ["data", "partial"]);
|
|
435
|
+
var queryResult = __assign(__assign({ data: data }, resultWithoutPartial), { client: client, observable: observable, variables: observable.variables, called: result !== ssrDisabledResult && result !== skipStandbyResult, previousData: previousData });
|
|
436
|
+
// non-enumerable property to hold the original result, for referential equality checks
|
|
437
|
+
Object.defineProperty(queryResult, originalResult, { value: result });
|
|
438
|
+
if (!queryResult.error && isNonEmptyArray(result.errors)) {
|
|
439
|
+
// Until a set naming convention for networkError and graphQLErrors is
|
|
440
|
+
// decided upon, we map errors (graphQLErrors) to the error options.
|
|
441
|
+
// TODO: Is it possible for both result.error and result.errors to be
|
|
442
|
+
// defined here?
|
|
443
|
+
queryResult.error = new ApolloError({ graphQLErrors: result.errors });
|
|
444
|
+
}
|
|
445
|
+
return queryResult;
|
|
446
|
+
}
|
|
447
|
+
function unsafeHandlePartialRefetch(result, observable, partialRefetch) {
|
|
448
|
+
// TODO: This code should be removed when the partialRefetch option is
|
|
449
|
+
// removed. I was unable to get this hook to behave reasonably in certain
|
|
450
|
+
// edge cases when this block was put in an effect.
|
|
451
|
+
if (result.partial &&
|
|
452
|
+
partialRefetch &&
|
|
453
|
+
!result.loading &&
|
|
454
|
+
(!result.data || Object.keys(result.data).length === 0) &&
|
|
455
|
+
observable.options.fetchPolicy !== "cache-only") {
|
|
456
|
+
observable.refetch();
|
|
457
|
+
return __assign(__assign({}, result), { loading: true, networkStatus: NetworkStatus.refetch });
|
|
458
|
+
}
|
|
459
|
+
return result;
|
|
460
|
+
}
|
|
461
|
+
var ssrDisabledResult = maybeDeepFreeze({
|
|
462
|
+
loading: true,
|
|
463
|
+
data: void 0,
|
|
464
|
+
error: void 0,
|
|
465
|
+
networkStatus: NetworkStatus.loading,
|
|
466
|
+
});
|
|
467
|
+
var skipStandbyResult = maybeDeepFreeze({
|
|
468
|
+
loading: false,
|
|
469
|
+
data: void 0,
|
|
470
|
+
error: void 0,
|
|
471
|
+
networkStatus: NetworkStatus.ready,
|
|
472
|
+
});
|
|
473
|
+
function bindObservableMethods(observable) {
|
|
474
|
+
return {
|
|
475
|
+
refetch: observable.refetch.bind(observable),
|
|
476
|
+
reobserve: observable.reobserve.bind(observable),
|
|
477
|
+
fetchMore: observable.fetchMore.bind(observable),
|
|
478
|
+
updateQuery: observable.updateQuery.bind(observable),
|
|
479
|
+
startPolling: observable.startPolling.bind(observable),
|
|
480
|
+
stopPolling: observable.stopPolling.bind(observable),
|
|
481
|
+
subscribeToMore: observable.subscribeToMore.bind(observable),
|
|
482
482
|
};
|
|
483
|
-
|
|
484
|
-
}());
|
|
483
|
+
}
|
|
485
484
|
//# sourceMappingURL=useQuery.js.map
|