UNPKG

@apollo/client

Version:

A fully-featured caching GraphQL client.

300 lines 14 kB
import { __assign, __rest } from "tslib"; import { invariant } from "../../utilities/globals/index.js"; import { useCallback, useContext, useMemo, useRef, useState, } from 'react'; import { useSyncExternalStore } from "./useSyncExternalStore.js"; import { equal } from '@wry/equality'; import { mergeOptions } from "../../core/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, canUseWeakSet, compact, isNonEmptyArray, maybeDeepFreeze } from "../../utilities/index.js"; var hasOwnProperty = Object.prototype.hasOwnProperty; 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 = useRef(); if (!stateRef.current || client !== stateRef.current.client || query !== stateRef.current.query) { stateRef.current = new InternalState(client, query, stateRef.current); } var state = stateRef.current; var _a = useState(0), _tick = _a[0], setTick = _a[1]; state.forceUpdate = function () { setTick(function (tick) { return tick + 1; }); }; return state; } var InternalState = (function () { function InternalState(client, query, previous) { this.client = client; this.query = query; this.asyncResolveFns = new Set(); this.optionsToIgnoreOnce = new (canUseWeakSet ? WeakSet : Set)(); 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.toQueryResultCache = new (canUseWeakMap ? WeakMap : Map)(); verifyDocumentType(query, DocumentType.Query); var previousResult = previous && previous.result; var previousData = previousResult && previousResult.data; if (previousData) { this.previousData = previousData; } } InternalState.prototype.forceUpdate = function () { __DEV__ && invariant.warn("Calling default no-op implementation of InternalState#forceUpdate"); }; InternalState.prototype.asyncUpdate = function (signal) { var _this = this; return new Promise(function (resolve, reject) { var watchQueryOptions = _this.watchQueryOptions; var handleAborted = function () { _this.asyncResolveFns.delete(resolve); _this.optionsToIgnoreOnce.delete(watchQueryOptions); signal.removeEventListener('abort', handleAborted); reject(signal.reason); }; _this.asyncResolveFns.add(resolve); _this.optionsToIgnoreOnce.add(watchQueryOptions); signal.addEventListener('abort', handleAborted); _this.forceUpdate(); }); }; InternalState.prototype.useQuery = function (options) { var _this = this; this.renderPromises = useContext(getApolloContext()).renderPromises; this.useOptions(options); var obsQuery = this.useObservableQuery(); var result = useSyncExternalStore(useCallback(function () { if (_this.renderPromises) { return function () { }; } var onNext = function () { var previousResult = _this.result; var result = obsQuery.getCurrentResult(); if (previousResult && previousResult.loading === result.loading && previousResult.networkStatus === result.networkStatus && equal(previousResult.data, result.data)) { return; } _this.setResult(result); }; var onError = function (error) { var last = obsQuery["last"]; subscription.unsubscribe(); try { obsQuery.resetLastResults(); subscription = obsQuery.subscribe(onNext, onError); } finally { obsQuery["last"] = last; } if (!hasOwnProperty.call(error, 'graphQLErrors')) { 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); return function () { return subscription.unsubscribe(); }; }, [ obsQuery, this.renderPromises, this.client.disableNetworkFetches, ]), function () { return _this.getCurrentResult(); }, function () { return _this.getCurrentResult(); }); this.unsafeHandlePartialRefetch(result); var queryResult = this.toQueryResult(result); if (!queryResult.loading && this.asyncResolveFns.size) { this.asyncResolveFns.forEach(function (resolve) { return resolve(queryResult); }); this.asyncResolveFns.clear(); } return queryResult; }; InternalState.prototype.useOptions = function (options) { var _a; var watchQueryOptions = this.createWatchQueryOptions(this.queryHookOptions = options); var currentWatchQueryOptions = this.watchQueryOptions; if (this.optionsToIgnoreOnce.has(currentWatchQueryOptions) || !equal(watchQueryOptions, currentWatchQueryOptions)) { this.watchQueryOptions = watchQueryOptions; if (currentWatchQueryOptions && this.observable) { this.optionsToIgnoreOnce.delete(currentWatchQueryOptions); this.observable.reobserve(this.getObsQueryOptions()); this.previousData = ((_a = this.result) === null || _a === void 0 ? void 0 : _a.data) || this.previousData; this.result = void 0; } } 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) { this.result = this.ssrDisabledResult; } else if (this.queryHookOptions.skip || this.watchQueryOptions.fetchPolicy === 'standby') { 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); } toMerge.push(compact(this.observable && this.observable.options, this.watchQueryOptions)); return toMerge.reduce(mergeOptions); }; 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, otherOptions = __rest(_a, ["skip", "ssr", "onCompleted", "onError", "defaultOptions"]); var watchQueryOptions = Object.assign(otherOptions, { query: this.query }); if (this.renderPromises && (watchQueryOptions.fetchPolicy === 'network-only' || watchQueryOptions.fetchPolicy === 'cache-and-network')) { 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; 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"); }; InternalState.prototype.onCompleted = function (data) { }; InternalState.prototype.onError = function (error) { }; InternalState.prototype.useObservableQuery = function () { var obsQuery = this.observable = this.renderPromises && this.renderPromises.getSSRObservable(this.watchQueryOptions) || this.observable || this.client.watchQuery(this.getObsQueryOptions()); this.obsQueryFields = 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) { 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; this.forceUpdate(); this.handleErrorOrCompleted(nextResult); }; InternalState.prototype.handleErrorOrCompleted = function (result) { var _this = this; if (!result.loading) { var error_1 = this.toApolloError(result); Promise.resolve().then(function () { if (error_1) { _this.onError(error_1); } else if (result.data) { _this.onCompleted(result.data); } }).catch(function (error) { __DEV__ && invariant.warn(error); }); } }; InternalState.prototype.toApolloError = function (result) { return isNonEmptyArray(result.errors) ? new ApolloError({ graphQLErrors: result.errors }) : result.error; }; InternalState.prototype.getCurrentResult = function () { 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)) { queryResult.error = new ApolloError({ graphQLErrors: result.errors }); } return queryResult; }; InternalState.prototype.unsafeHandlePartialRefetch = function (result) { 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