@shopify/react-graphql
Version:
Tools for creating type-safe and asynchronous GraphQL components for React
147 lines (129 loc) • 5.46 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var _rollupPluginBabelHelpers = require('../_virtual/_rollupPluginBabelHelpers.js');
var React = require('react');
var apolloClient$1 = require('apollo-client');
var reactEffect = require('@shopify/react-effect');
var apolloClient = require('./apollo-client.js');
var graphqlDocument = require('./graphql-document.js');
function useQuery(queryOrAsyncQuery, ...optionsPart) {
const [options = {}] = optionsPart;
const {
skip = false,
fetchPolicy,
errorPolicy,
pollInterval,
client: overrideClient,
notifyOnNetworkStatusChange,
context,
ssr = true
} = options;
const variables = options.variables || {};
const client = apolloClient['default'](overrideClient);
if (typeof window === 'undefined' && (skip || fetchPolicy === 'no-cache' || !ssr)) {
return createDefaultResult(client, variables);
}
const query = graphqlDocument['default'](queryOrAsyncQuery);
const normalizedFetchPolicy = typeof window === 'undefined' && (fetchPolicy === 'network-only' || fetchPolicy === 'cache-and-network') ? 'cache-first' : fetchPolicy;
const serializedVariables = variables && JSON.stringify(variables);
const watchQueryOptions = React.useMemo(() => {
if (!query) {
return null;
}
return {
query,
context,
variables,
fetchPolicy: normalizedFetchPolicy,
errorPolicy,
pollInterval,
notifyOnNetworkStatusChange
}; // eslint-disable-next-line react-hooks/exhaustive-deps
}, [query, // eslint-disable-next-line react-hooks/exhaustive-deps
context && JSON.stringify(context), serializedVariables, normalizedFetchPolicy, errorPolicy, pollInterval, notifyOnNetworkStatusChange]);
const queryObservable = React.useMemo(() => {
if (skip || !watchQueryOptions) {
return;
}
return client.watchQuery(watchQueryOptions);
}, [client, skip, watchQueryOptions]);
reactEffect.useServerEffect(() => {
if (queryObservable == null) {
return;
}
const result = queryObservable.getCurrentResult();
return result.loading ? queryObservable.result() : undefined;
});
const defaultResult = React.useMemo(() => createDefaultResult(client, variables, queryObservable), // eslint-disable-next-line react-hooks/exhaustive-deps
[queryObservable, client, serializedVariables]);
const [responseId, setResponseId] = React.useState(0);
React.useEffect(() => {
if (skip || !queryObservable) {
return;
}
const invalidateCurrentResult = () => {
setResponseId(x => x + 1);
};
const subscription = queryObservable.subscribe(invalidateCurrentResult, invalidateCurrentResult);
return () => {
subscription.unsubscribe();
};
}, [skip, queryObservable]);
const previousData = React.useRef(undefined);
const currentResult = React.useMemo(() => {
// must of the logic below are lifted from
// https://github.com/apollographql/react-apollo/blob/22f8ebf52b26b348d6be905d5b7fbbfea51c1541/src/Query.tsx#L410-L477
if (skip) {
return defaultResult;
}
if (!queryObservable) {
return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, defaultResult), {}, {
// while documentNode is loading
loading: true
});
}
const result = queryObservable.getCurrentResult();
const {
fetchPolicy
} = queryObservable.options;
const hasError = result.errors && result.errors.length > 0;
let data = result.data;
if (result.loading) {
data = previousData.current || result && result.data ? _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, previousData.current || {}), result && result.data || {}) : undefined;
} else if (hasError) {
data = (queryObservable.getLastResult() || {}).data;
} else if (fetchPolicy === 'no-cache' && (!result.data || Object.keys(result.data).length === 0)) {
data = previousData.current;
} else {
previousData.current = result.data;
}
return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, defaultResult), {}, {
data,
error: hasError ? new apolloClient$1.ApolloError({
graphQLErrors: result.errors
}) : result.error,
networkStatus: result.networkStatus,
loading: result.loading
}); // eslint-disable-next-line react-hooks/exhaustive-deps
}, [responseId, skip, queryObservable, defaultResult, previousData]);
return currentResult;
}
function createDefaultResult(client, variables, queryObservable) {
return {
data: undefined,
error: undefined,
networkStatus: undefined,
loading: false,
called: false,
variables: queryObservable ? queryObservable.variables : variables,
refetch: queryObservable ? queryObservable.refetch.bind(queryObservable) : noop,
fetchMore: queryObservable ? queryObservable.fetchMore.bind(queryObservable) : noop,
updateQuery: queryObservable ? queryObservable.updateQuery.bind(queryObservable) : noop,
startPolling: queryObservable ? queryObservable.startPolling.bind(queryObservable) : noop,
stopPolling: queryObservable ? queryObservable.stopPolling.bind(queryObservable) : noop,
subscribeToMore: queryObservable ? queryObservable.subscribeToMore.bind(queryObservable) : noop,
client
};
}
function noop() {}
exports.default = useQuery;