UNPKG

@shopify/react-graphql

Version:

Tools for creating type-safe and asynchronous GraphQL components for React

147 lines (129 loc) 5.46 kB
'use strict'; 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;