react-apollo-hooks
Version:
Use [Apollo Client](https://github.com/apollographql/apollo-client) as React [hooks](https://reactjs.org/docs/hooks-intro.html).
134 lines (122 loc) • 5.56 kB
JavaScript
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
import { ApolloError } from 'apollo-client';
import { useContext, useEffect, useMemo, useState } from 'react';
import { useApolloClient } from './ApolloContext';
import { SSRContext } from './internal/SSRContext';
import actHack from './internal/actHack';
import { getCachedObservableQuery, invalidateCachedObservableQuery } from './queryCache';
import { compact, objToKey } from './utils';
export function useQuery(query, _temp) {
var _ref = _temp === void 0 ? {} : _temp,
_ref$ssr = _ref.ssr,
ssr = _ref$ssr === void 0 ? true : _ref$ssr,
_ref$skip = _ref.skip,
skip = _ref$skip === void 0 ? false : _ref$skip,
_ref$suspend = _ref.suspend,
suspend = _ref$suspend === void 0 ? false : _ref$suspend,
pollInterval = _ref.pollInterval,
_ref$notifyOnNetworkS = _ref.notifyOnNetworkStatusChange,
notifyOnNetworkStatusChange = _ref$notifyOnNetworkS === void 0 ? false : _ref$notifyOnNetworkS,
overrideClient = _ref.client,
context = _ref.context,
metadata = _ref.metadata,
variables = _ref.variables,
actualCachePolicy = _ref.fetchPolicy,
errorPolicy = _ref.errorPolicy,
fetchResults = _ref.fetchResults;
var client = useApolloClient(overrideClient);
var ssrManager = useContext(SSRContext);
var ssrInUse = ssr && ssrManager; // Skips when `skip: true` or SSRContext passed but `ssr: false`
var shouldSkip = skip || ssrManager != null && !ssr;
var fetchPolicy = ssrInUse && ( // Taken from https://github.com/apollographql/react-apollo/blob/2d7e48b7d0c26e792e1ed26e98bb84d8fba5bb8a/src/Query.tsx#L167-L169
actualCachePolicy === 'network-only' || actualCachePolicy === 'cache-and-network') ? 'cache-first' : actualCachePolicy;
var watchQueryOptions = useMemo(function () {
return compact({
context: context,
errorPolicy: errorPolicy,
fetchPolicy: fetchPolicy,
fetchResults: fetchResults,
metadata: metadata,
notifyOnNetworkStatusChange: notifyOnNetworkStatusChange,
pollInterval: pollInterval,
query: query,
variables: variables
});
}, [query, pollInterval, notifyOnNetworkStatusChange, context && objToKey(context), metadata && objToKey(metadata), variables && objToKey(variables), fetchPolicy, errorPolicy, fetchResults]);
var observableQuery = useMemo(function () {
return getCachedObservableQuery(client, watchQueryOptions);
}, [client, watchQueryOptions]);
var _useState = useState(0),
responseId = _useState[0],
setResponseId = _useState[1];
var currentResult = useMemo(function () {
var result = observableQuery.currentResult();
return {
data: result.data,
error: result.errors && result.errors.length > 0 ? new ApolloError({
graphQLErrors: result.errors
}) : result.error,
errors: result.errors,
loading: result.loading,
// don't try to return `networkStatus` when suspense it's used
// because it's unreliable in that case
// https://github.com/trojanowski/react-apollo-hooks/pull/68
networkStatus: suspend ? undefined : result.networkStatus,
partial: result.partial
};
}, [shouldSkip, responseId, observableQuery]);
useEffect(function () {
if (shouldSkip) {
return;
}
var invalidateCurrentResult = function invalidateCurrentResult() {
// A hack to get rid React warnings during tests. The default
// implementation of `actHack` just invokes the callback immediately.
// In tests, it's replaced with `act` from react-testing-library.
// A better solution welcome.
actHack(function () {
setResponseId(function (x) {
return x + 1;
});
});
};
var subscription = observableQuery.subscribe(invalidateCurrentResult, invalidateCurrentResult);
invalidateCachedObservableQuery(client, watchQueryOptions);
return function () {
subscription.unsubscribe();
};
}, [shouldSkip, observableQuery]);
ensureSupportedFetchPolicy(suspend, fetchPolicy);
var helpers = {
fetchMore: observableQuery.fetchMore.bind(observableQuery),
refetch: observableQuery.refetch.bind(observableQuery),
startPolling: observableQuery.startPolling.bind(observableQuery),
stopPolling: observableQuery.stopPolling.bind(observableQuery),
updateQuery: observableQuery.updateQuery.bind(observableQuery)
};
if (shouldSkip) {
// Taken from https://github.com/apollographql/react-apollo/blob/5cb63b3625ce5e4a3d3e4ba132eaec2a38ef5d90/src/Query.tsx#L376-L381
return _extends({}, helpers, {
data: undefined,
error: undefined,
loading: false,
networkStatus: undefined
});
}
if (currentResult.partial) {
if (suspend) {
// throw a promise - use the react suspense to wait until the data is
// available
throw observableQuery.result();
}
if (ssrInUse) {
ssrManager.register(observableQuery.result());
}
}
return _extends({}, helpers, currentResult);
}
function ensureSupportedFetchPolicy(suspend, fetchPolicy) {
if (suspend && fetchPolicy && fetchPolicy !== 'cache-first') {
throw new Error("Fetch policy " + fetchPolicy + " is not supported without 'suspend: false'");
}
}