You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
467 lines
24 KiB
467 lines
24 KiB
4 months ago
|
import { __assign, __rest } from "tslib";
|
||
|
import { invariant } from "../../utilities/globals/index.js";
|
||
|
import * as React from "rehackt";
|
||
|
import { useSyncExternalStore } from "./useSyncExternalStore.js";
|
||
|
import { equal } from "@wry/equality";
|
||
|
import { mergeOptions } from "../../utilities/index.js";
|
||
|
import { getApolloContext } from "../context/index.js";
|
||
|
import { ApolloError } from "../../errors/index.js";
|
||
|
import { NetworkStatus } from "../../core/index.js";
|
||
|
import { DocumentType, verifyDocumentType } from "../parser/index.js";
|
||
|
import { useApolloClient } from "./useApolloClient.js";
|
||
|
import { canUseWeakMap, compact, isNonEmptyArray, maybeDeepFreeze, } from "../../utilities/index.js";
|
||
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||
|
/**
|
||
|
* A hook for executing queries in an Apollo application.
|
||
|
*
|
||
|
* To run a query within a React component, call `useQuery` and pass it a GraphQL query document.
|
||
|
*
|
||
|
* When your component renders, `useQuery` returns an object from Apollo Client that contains `loading`, `error`, and `data` properties you can use to render your UI.
|
||
|
*
|
||
|
* > Refer to the [Queries](https://www.apollographql.com/docs/react/data/queries) section for a more in-depth overview of `useQuery`.
|
||
|
*
|
||
|
* @example
|
||
|
* ```jsx
|
||
|
* import { gql, useQuery } from '@apollo/client';
|
||
|
*
|
||
|
* const GET_GREETING = gql`
|
||
|
* query GetGreeting($language: String!) {
|
||
|
* greeting(language: $language) {
|
||
|
* message
|
||
|
* }
|
||
|
* }
|
||
|
* `;
|
||
|
*
|
||
|
* function Hello() {
|
||
|
* const { loading, error, data } = useQuery(GET_GREETING, {
|
||
|
* variables: { language: 'english' },
|
||
|
* });
|
||
|
* if (loading) return <p>Loading ...</p>;
|
||
|
* return <h1>Hello {data.greeting.message}!</h1>;
|
||
|
* }
|
||
|
* ```
|
||
|
* @since 3.0.0
|
||
|
* @param query - A GraphQL query document parsed into an AST by `gql`.
|
||
|
* @param options - Options to control how the query is executed.
|
||
|
* @returns Query result object
|
||
|
*/
|
||
|
export function useQuery(query, options) {
|
||
|
if (options === void 0) { options = Object.create(null); }
|
||
|
return useInternalState(useApolloClient(options.client), query).useQuery(options);
|
||
|
}
|
||
|
export function useInternalState(client, query) {
|
||
|
var stateRef = React.useRef();
|
||
|
if (!stateRef.current ||
|
||
|
client !== stateRef.current.client ||
|
||
|
query !== stateRef.current.query) {
|
||
|
stateRef.current = new InternalState(client, query, stateRef.current);
|
||
|
}
|
||
|
var state = stateRef.current;
|
||
|
// By default, InternalState.prototype.forceUpdate is an empty function, but
|
||
|
// we replace it here (before anyone has had a chance to see this state yet)
|
||
|
// with a function that unconditionally forces an update, using the latest
|
||
|
// setTick function. Updating this state by calling state.forceUpdate is the
|
||
|
// only way we trigger React component updates (no other useState calls within
|
||
|
// the InternalState class).
|
||
|
state.forceUpdateState = React.useReducer(function (tick) { return tick + 1; }, 0)[1];
|
||
|
return state;
|
||
|
}
|
||
|
var InternalState = /** @class */ (function () {
|
||
|
function InternalState(client, query, previous) {
|
||
|
var _this = this;
|
||
|
this.client = client;
|
||
|
this.query = query;
|
||
|
/**
|
||
|
* Will be overwritten by the `useSyncExternalStore` "force update" method
|
||
|
* whenever it is available and reset to `forceUpdateState` when it isn't.
|
||
|
*/
|
||
|
this.forceUpdate = function () { return _this.forceUpdateState(); };
|
||
|
this.ssrDisabledResult = maybeDeepFreeze({
|
||
|
loading: true,
|
||
|
data: void 0,
|
||
|
error: void 0,
|
||
|
networkStatus: NetworkStatus.loading,
|
||
|
});
|
||
|
this.skipStandbyResult = maybeDeepFreeze({
|
||
|
loading: false,
|
||
|
data: void 0,
|
||
|
error: void 0,
|
||
|
networkStatus: NetworkStatus.ready,
|
||
|
});
|
||
|
// This cache allows the referential stability of this.result (as returned by
|
||
|
// getCurrentResult) to translate into referential stability of the resulting
|
||
|
// QueryResult object returned by toQueryResult.
|
||
|
this.toQueryResultCache = new (canUseWeakMap ? WeakMap : Map)();
|
||
|
verifyDocumentType(query, DocumentType.Query);
|
||
|
// Reuse previousData from previous InternalState (if any) to provide
|
||
|
// continuity of previousData even if/when the query or client changes.
|
||
|
var previousResult = previous && previous.result;
|
||
|
var previousData = previousResult && previousResult.data;
|
||
|
if (previousData) {
|
||
|
this.previousData = previousData;
|
||
|
}
|
||
|
}
|
||
|
/**
|
||
|
* Forces an update using local component state.
|
||
|
* As this is not batched with `useSyncExternalStore` updates,
|
||
|
* this is only used as a fallback if the `useSyncExternalStore` "force update"
|
||
|
* method is not registered at the moment.
|
||
|
* See https://github.com/facebook/react/issues/25191
|
||
|
* */
|
||
|
InternalState.prototype.forceUpdateState = function () {
|
||
|
// Replaced (in useInternalState) with a method that triggers an update.
|
||
|
globalThis.__DEV__ !== false && invariant.warn(51);
|
||
|
};
|
||
|
InternalState.prototype.executeQuery = function (options) {
|
||
|
var _this = this;
|
||
|
var _a;
|
||
|
if (options.query) {
|
||
|
Object.assign(this, { query: options.query });
|
||
|
}
|
||
|
this.watchQueryOptions = this.createWatchQueryOptions((this.queryHookOptions = options));
|
||
|
var concast = this.observable.reobserveAsConcast(this.getObsQueryOptions());
|
||
|
// Make sure getCurrentResult returns a fresh ApolloQueryResult<TData>,
|
||
|
// but save the current data as this.previousData, just like setResult
|
||
|
// usually does.
|
||
|
this.previousData = ((_a = this.result) === null || _a === void 0 ? void 0 : _a.data) || this.previousData;
|
||
|
this.result = void 0;
|
||
|
this.forceUpdate();
|
||
|
return new Promise(function (resolve) {
|
||
|
var result;
|
||
|
// Subscribe to the concast independently of the ObservableQuery in case
|
||
|
// the component gets unmounted before the promise resolves. This prevents
|
||
|
// the concast from terminating early and resolving with `undefined` when
|
||
|
// there are no more subscribers for the concast.
|
||
|
concast.subscribe({
|
||
|
next: function (value) {
|
||
|
result = value;
|
||
|
},
|
||
|
error: function () {
|
||
|
resolve(_this.toQueryResult(_this.observable.getCurrentResult()));
|
||
|
},
|
||
|
complete: function () {
|
||
|
resolve(_this.toQueryResult(result));
|
||
|
},
|
||
|
});
|
||
|
});
|
||
|
};
|
||
|
// Methods beginning with use- should be called according to the standard
|
||
|
// rules of React hooks: only at the top level of the calling function, and
|
||
|
// without any dynamic conditional logic.
|
||
|
InternalState.prototype.useQuery = function (options) {
|
||
|
var _this = this;
|
||
|
// The renderPromises field gets initialized here in the useQuery method, at
|
||
|
// the beginning of everything (for a given component rendering, at least),
|
||
|
// so we can safely use this.renderPromises in other/later InternalState
|
||
|
// methods without worrying it might be uninitialized. Even after
|
||
|
// initialization, this.renderPromises is usually undefined (unless SSR is
|
||
|
// happening), but that's fine as long as it has been initialized that way,
|
||
|
// rather than left uninitialized.
|
||
|
this.renderPromises = React.useContext(getApolloContext()).renderPromises;
|
||
|
this.useOptions(options);
|
||
|
var obsQuery = this.useObservableQuery();
|
||
|
var result = useSyncExternalStore(React.useCallback(function (handleStoreChange) {
|
||
|
if (_this.renderPromises) {
|
||
|
return function () { };
|
||
|
}
|
||
|
_this.forceUpdate = handleStoreChange;
|
||
|
var onNext = function () {
|
||
|
var previousResult = _this.result;
|
||
|
// We use `getCurrentResult()` instead of the onNext argument because
|
||
|
// the values differ slightly. Specifically, loading results will have
|
||
|
// an empty object for data instead of `undefined` for some reason.
|
||
|
var result = obsQuery.getCurrentResult();
|
||
|
// Make sure we're not attempting to re-render similar results
|
||
|
if (previousResult &&
|
||
|
previousResult.loading === result.loading &&
|
||
|
previousResult.networkStatus === result.networkStatus &&
|
||
|
equal(previousResult.data, result.data)) {
|
||
|
return;
|
||
|
}
|
||
|
_this.setResult(result);
|
||
|
};
|
||
|
var onError = function (error) {
|
||
|
subscription.unsubscribe();
|
||
|
subscription = obsQuery.resubscribeAfterError(onNext, onError);
|
||
|
if (!hasOwnProperty.call(error, "graphQLErrors")) {
|
||
|
// The error is not a GraphQL error
|
||
|
throw error;
|
||
|
}
|
||
|
var previousResult = _this.result;
|
||
|
if (!previousResult ||
|
||
|
(previousResult && previousResult.loading) ||
|
||
|
!equal(error, previousResult.error)) {
|
||
|
_this.setResult({
|
||
|
data: (previousResult && previousResult.data),
|
||
|
error: error,
|
||
|
loading: false,
|
||
|
networkStatus: NetworkStatus.error,
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
var subscription = obsQuery.subscribe(onNext, onError);
|
||
|
// Do the "unsubscribe" with a short delay.
|
||
|
// This way, an existing subscription can be reused without an additional
|
||
|
// request if "unsubscribe" and "resubscribe" to the same ObservableQuery
|
||
|
// happen in very fast succession.
|
||
|
return function () {
|
||
|
setTimeout(function () { return subscription.unsubscribe(); });
|
||
|
_this.forceUpdate = function () { return _this.forceUpdateState(); };
|
||
|
};
|
||
|
}, [
|
||
|
// We memoize the subscribe function using useCallback and the following
|
||
|
// dependency keys, because the subscribe function reference is all that
|
||
|
// useSyncExternalStore uses internally as a dependency key for the
|
||
|
// useEffect ultimately responsible for the subscription, so we are
|
||
|
// effectively passing this dependency array to that useEffect buried
|
||
|
// inside useSyncExternalStore, as desired.
|
||
|
obsQuery,
|
||
|
this.renderPromises,
|
||
|
this.client.disableNetworkFetches,
|
||
|
]), function () { return _this.getCurrentResult(); }, function () { return _this.getCurrentResult(); });
|
||
|
// TODO Remove this method when we remove support for options.partialRefetch.
|
||
|
this.unsafeHandlePartialRefetch(result);
|
||
|
return this.toQueryResult(result);
|
||
|
};
|
||
|
InternalState.prototype.useOptions = function (options) {
|
||
|
var _a;
|
||
|
var watchQueryOptions = this.createWatchQueryOptions((this.queryHookOptions = options));
|
||
|
// Update this.watchQueryOptions, but only when they have changed, which
|
||
|
// allows us to depend on the referential stability of
|
||
|
// this.watchQueryOptions elsewhere.
|
||
|
var currentWatchQueryOptions = this.watchQueryOptions;
|
||
|
if (!equal(watchQueryOptions, currentWatchQueryOptions)) {
|
||
|
this.watchQueryOptions = watchQueryOptions;
|
||
|
if (currentWatchQueryOptions && this.observable) {
|
||
|
// Though it might be tempting to postpone this reobserve call to the
|
||
|
// useEffect block, we need getCurrentResult to return an appropriate
|
||
|
// loading:true result synchronously (later within the same call to
|
||
|
// useQuery). Since we already have this.observable here (not true for
|
||
|
// the very first call to useQuery), we are not initiating any new
|
||
|
// subscriptions, though it does feel less than ideal that reobserve
|
||
|
// (potentially) kicks off a network request (for example, when the
|
||
|
// variables have changed), which is technically a side-effect.
|
||
|
this.observable.reobserve(this.getObsQueryOptions());
|
||
|
// Make sure getCurrentResult returns a fresh ApolloQueryResult<TData>,
|
||
|
// but save the current data as this.previousData, just like setResult
|
||
|
// usually does.
|
||
|
this.previousData = ((_a = this.result) === null || _a === void 0 ? void 0 : _a.data) || this.previousData;
|
||
|
this.result = void 0;
|
||
|
}
|
||
|
}
|
||
|
// Make sure state.onCompleted and state.onError always reflect the latest
|
||
|
// options.onCompleted and options.onError callbacks provided to useQuery,
|
||
|
// since those functions are often recreated every time useQuery is called.
|
||
|
// Like the forceUpdate method, the versions of these methods inherited from
|
||
|
// InternalState.prototype are empty no-ops, but we can override them on the
|
||
|
// base state object (without modifying the prototype).
|
||
|
this.onCompleted =
|
||
|
options.onCompleted || InternalState.prototype.onCompleted;
|
||
|
this.onError = options.onError || InternalState.prototype.onError;
|
||
|
if ((this.renderPromises || this.client.disableNetworkFetches) &&
|
||
|
this.queryHookOptions.ssr === false &&
|
||
|
!this.queryHookOptions.skip) {
|
||
|
// If SSR has been explicitly disabled, and this function has been called
|
||
|
// on the server side, return the default loading state.
|
||
|
this.result = this.ssrDisabledResult;
|
||
|
}
|
||
|
else if (this.queryHookOptions.skip ||
|
||
|
this.watchQueryOptions.fetchPolicy === "standby") {
|
||
|
// When skipping a query (ie. we're not querying for data but still want to
|
||
|
// render children), make sure the `data` is cleared out and `loading` is
|
||
|
// set to `false` (since we aren't loading anything).
|
||
|
//
|
||
|
// NOTE: We no longer think this is the correct behavior. Skipping should
|
||
|
// not automatically set `data` to `undefined`, but instead leave the
|
||
|
// previous data in place. In other words, skipping should not mandate that
|
||
|
// previously received data is all of a sudden removed. Unfortunately,
|
||
|
// changing this is breaking, so we'll have to wait until Apollo Client 4.0
|
||
|
// to address this.
|
||
|
this.result = this.skipStandbyResult;
|
||
|
}
|
||
|
else if (this.result === this.ssrDisabledResult ||
|
||
|
this.result === this.skipStandbyResult) {
|
||
|
this.result = void 0;
|
||
|
}
|
||
|
};
|
||
|
InternalState.prototype.getObsQueryOptions = function () {
|
||
|
var toMerge = [];
|
||
|
var globalDefaults = this.client.defaultOptions.watchQuery;
|
||
|
if (globalDefaults)
|
||
|
toMerge.push(globalDefaults);
|
||
|
if (this.queryHookOptions.defaultOptions) {
|
||
|
toMerge.push(this.queryHookOptions.defaultOptions);
|
||
|
}
|
||
|
// We use compact rather than mergeOptions for this part of the merge,
|
||
|
// because we want watchQueryOptions.variables (if defined) to replace
|
||
|
// this.observable.options.variables whole. This replacement allows
|
||
|
// removing variables by removing them from the variables input to
|
||
|
// useQuery. If the variables were always merged together (rather than
|
||
|
// replaced), there would be no way to remove existing variables.
|
||
|
// However, the variables from options.defaultOptions and globalDefaults
|
||
|
// (if provided) should be merged, to ensure individual defaulted
|
||
|
// variables always have values, if not otherwise defined in
|
||
|
// observable.options or watchQueryOptions.
|
||
|
toMerge.push(compact(this.observable && this.observable.options, this.watchQueryOptions));
|
||
|
return toMerge.reduce(mergeOptions);
|
||
|
};
|
||
|
// A function to massage options before passing them to ObservableQuery.
|
||
|
InternalState.prototype.createWatchQueryOptions = function (_a) {
|
||
|
var _b;
|
||
|
if (_a === void 0) { _a = {}; }
|
||
|
var skip = _a.skip, ssr = _a.ssr, onCompleted = _a.onCompleted, onError = _a.onError, defaultOptions = _a.defaultOptions,
|
||
|
// The above options are useQuery-specific, so this ...otherOptions spread
|
||
|
// makes otherOptions almost a WatchQueryOptions object, except for the
|
||
|
// query property that we add below.
|
||
|
otherOptions = __rest(_a, ["skip", "ssr", "onCompleted", "onError", "defaultOptions"]);
|
||
|
// This Object.assign is safe because otherOptions is a fresh ...rest object
|
||
|
// that did not exist until just now, so modifications are still allowed.
|
||
|
var watchQueryOptions = Object.assign(otherOptions, { query: this.query });
|
||
|
if (this.renderPromises &&
|
||
|
(watchQueryOptions.fetchPolicy === "network-only" ||
|
||
|
watchQueryOptions.fetchPolicy === "cache-and-network")) {
|
||
|
// this behavior was added to react-apollo without explanation in this PR
|
||
|
// https://github.com/apollographql/react-apollo/pull/1579
|
||
|
watchQueryOptions.fetchPolicy = "cache-first";
|
||
|
}
|
||
|
if (!watchQueryOptions.variables) {
|
||
|
watchQueryOptions.variables = {};
|
||
|
}
|
||
|
if (skip) {
|
||
|
var _c = watchQueryOptions.fetchPolicy, fetchPolicy = _c === void 0 ? this.getDefaultFetchPolicy() : _c, _d = watchQueryOptions.initialFetchPolicy, initialFetchPolicy = _d === void 0 ? fetchPolicy : _d;
|
||
|
// When skipping, we set watchQueryOptions.fetchPolicy initially to
|
||
|
// "standby", but we also need/want to preserve the initial non-standby
|
||
|
// fetchPolicy that would have been used if not skipping.
|
||
|
Object.assign(watchQueryOptions, {
|
||
|
initialFetchPolicy: initialFetchPolicy,
|
||
|
fetchPolicy: "standby",
|
||
|
});
|
||
|
}
|
||
|
else if (!watchQueryOptions.fetchPolicy) {
|
||
|
watchQueryOptions.fetchPolicy =
|
||
|
((_b = this.observable) === null || _b === void 0 ? void 0 : _b.options.initialFetchPolicy) ||
|
||
|
this.getDefaultFetchPolicy();
|
||
|
}
|
||
|
return watchQueryOptions;
|
||
|
};
|
||
|
InternalState.prototype.getDefaultFetchPolicy = function () {
|
||
|
var _a, _b;
|
||
|
return (((_a = this.queryHookOptions.defaultOptions) === null || _a === void 0 ? void 0 : _a.fetchPolicy) ||
|
||
|
((_b = this.client.defaultOptions.watchQuery) === null || _b === void 0 ? void 0 : _b.fetchPolicy) ||
|
||
|
"cache-first");
|
||
|
};
|
||
|
// Defining these methods as no-ops on the prototype allows us to call
|
||
|
// state.onCompleted and/or state.onError without worrying about whether a
|
||
|
// callback was provided.
|
||
|
InternalState.prototype.onCompleted = function (data) { };
|
||
|
InternalState.prototype.onError = function (error) { };
|
||
|
InternalState.prototype.useObservableQuery = function () {
|
||
|
// See if there is an existing observable that was used to fetch the same
|
||
|
// data and if so, use it instead since it will contain the proper queryId
|
||
|
// to fetch the result set. This is used during SSR.
|
||
|
var obsQuery = (this.observable =
|
||
|
(this.renderPromises &&
|
||
|
this.renderPromises.getSSRObservable(this.watchQueryOptions)) ||
|
||
|
this.observable || // Reuse this.observable if possible (and not SSR)
|
||
|
this.client.watchQuery(this.getObsQueryOptions()));
|
||
|
this.obsQueryFields = React.useMemo(function () { return ({
|
||
|
refetch: obsQuery.refetch.bind(obsQuery),
|
||
|
reobserve: obsQuery.reobserve.bind(obsQuery),
|
||
|
fetchMore: obsQuery.fetchMore.bind(obsQuery),
|
||
|
updateQuery: obsQuery.updateQuery.bind(obsQuery),
|
||
|
startPolling: obsQuery.startPolling.bind(obsQuery),
|
||
|
stopPolling: obsQuery.stopPolling.bind(obsQuery),
|
||
|
subscribeToMore: obsQuery.subscribeToMore.bind(obsQuery),
|
||
|
}); }, [obsQuery]);
|
||
|
var ssrAllowed = !(this.queryHookOptions.ssr === false || this.queryHookOptions.skip);
|
||
|
if (this.renderPromises && ssrAllowed) {
|
||
|
this.renderPromises.registerSSRObservable(obsQuery);
|
||
|
if (obsQuery.getCurrentResult().loading) {
|
||
|
// TODO: This is a legacy API which could probably be cleaned up
|
||
|
this.renderPromises.addObservableQueryPromise(obsQuery);
|
||
|
}
|
||
|
}
|
||
|
return obsQuery;
|
||
|
};
|
||
|
InternalState.prototype.setResult = function (nextResult) {
|
||
|
var previousResult = this.result;
|
||
|
if (previousResult && previousResult.data) {
|
||
|
this.previousData = previousResult.data;
|
||
|
}
|
||
|
this.result = nextResult;
|
||
|
// Calling state.setResult always triggers an update, though some call sites
|
||
|
// perform additional equality checks before committing to an update.
|
||
|
this.forceUpdate();
|
||
|
this.handleErrorOrCompleted(nextResult, previousResult);
|
||
|
};
|
||
|
InternalState.prototype.handleErrorOrCompleted = function (result, previousResult) {
|
||
|
var _this = this;
|
||
|
if (!result.loading) {
|
||
|
var error_1 = this.toApolloError(result);
|
||
|
// wait a tick in case we are in the middle of rendering a component
|
||
|
Promise.resolve()
|
||
|
.then(function () {
|
||
|
if (error_1) {
|
||
|
_this.onError(error_1);
|
||
|
}
|
||
|
else if (result.data &&
|
||
|
(previousResult === null || previousResult === void 0 ? void 0 : previousResult.networkStatus) !== result.networkStatus &&
|
||
|
result.networkStatus === NetworkStatus.ready) {
|
||
|
_this.onCompleted(result.data);
|
||
|
}
|
||
|
})
|
||
|
.catch(function (error) {
|
||
|
globalThis.__DEV__ !== false && invariant.warn(error);
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
InternalState.prototype.toApolloError = function (result) {
|
||
|
return isNonEmptyArray(result.errors) ?
|
||
|
new ApolloError({ graphQLErrors: result.errors })
|
||
|
: result.error;
|
||
|
};
|
||
|
InternalState.prototype.getCurrentResult = function () {
|
||
|
// Using this.result as a cache ensures getCurrentResult continues returning
|
||
|
// the same (===) result object, unless state.setResult has been called, or
|
||
|
// we're doing server rendering and therefore override the result below.
|
||
|
if (!this.result) {
|
||
|
this.handleErrorOrCompleted((this.result = this.observable.getCurrentResult()));
|
||
|
}
|
||
|
return this.result;
|
||
|
};
|
||
|
InternalState.prototype.toQueryResult = function (result) {
|
||
|
var queryResult = this.toQueryResultCache.get(result);
|
||
|
if (queryResult)
|
||
|
return queryResult;
|
||
|
var data = result.data, partial = result.partial, resultWithoutPartial = __rest(result, ["data", "partial"]);
|
||
|
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 })));
|
||
|
if (!queryResult.error && isNonEmptyArray(result.errors)) {
|
||
|
// Until a set naming convention for networkError and graphQLErrors is
|
||
|
// decided upon, we map errors (graphQLErrors) to the error options.
|
||
|
// TODO: Is it possible for both result.error and result.errors to be
|
||
|
// defined here?
|
||
|
queryResult.error = new ApolloError({ graphQLErrors: result.errors });
|
||
|
}
|
||
|
return queryResult;
|
||
|
};
|
||
|
InternalState.prototype.unsafeHandlePartialRefetch = function (result) {
|
||
|
// WARNING: SIDE-EFFECTS IN THE RENDER FUNCTION
|
||
|
//
|
||
|
// TODO: This code should be removed when the partialRefetch option is
|
||
|
// removed. I was unable to get this hook to behave reasonably in certain
|
||
|
// edge cases when this block was put in an effect.
|
||
|
if (result.partial &&
|
||
|
this.queryHookOptions.partialRefetch &&
|
||
|
!result.loading &&
|
||
|
(!result.data || Object.keys(result.data).length === 0) &&
|
||
|
this.observable.options.fetchPolicy !== "cache-only") {
|
||
|
Object.assign(result, {
|
||
|
loading: true,
|
||
|
networkStatus: NetworkStatus.refetch,
|
||
|
});
|
||
|
this.observable.refetch();
|
||
|
}
|
||
|
};
|
||
|
return InternalState;
|
||
|
}());
|
||
|
//# sourceMappingURL=useQuery.js.map
|