import { ApolloQueryResult } from "apollo-client"; import { DocumentNode } from "graphql"; import { useEffect } from "react"; import { QueryResult, useQuery as useBaseQuery } from "react-apollo"; import { useIntl } from "react-intl"; import { commonMessages } from "@saleor/intl"; import { maybe, RequireAtLeastOne } from "@saleor/misc"; import useAppState from "./useAppState"; import useNotifier from "./useNotifier"; export interface LoadMore { loadMore: ( mergeFunc: (prev: TData, next: TData) => TData, extraVariables: Partial ) => Promise>; } type UseQuery = QueryResult & LoadMore; type UseQueryOpts = Partial<{ displayLoader: boolean; require: Array; skip: boolean; variables: TVariables; }>; type UseQueryHook = ( opts: UseQueryOpts ) => UseQuery; function makeQuery( query: DocumentNode ): UseQueryHook { function useQuery({ displayLoader, require, skip, variables }: UseQueryOpts): UseQuery { const notify = useNotifier(); const intl = useIntl(); const [, dispatchAppState] = useAppState(); const queryData = useBaseQuery(query, { context: { useBatching: true }, errorPolicy: "all", fetchPolicy: "cache-and-network", skip, variables }); useEffect(() => { if (displayLoader) { dispatchAppState({ payload: { value: queryData.loading }, type: "displayLoader" }); } }, [queryData.loading]); if (queryData.error) { if ( !queryData.error.graphQLErrors.every( err => maybe(() => err.extensions.exception.code) === "PermissionDenied" ) ) { notify({ text: intl.formatMessage(commonMessages.somethingWentWrong) }); } } const loadMore = ( mergeFunc: (previousResults: TData, fetchMoreResult: TData) => TData, extraVariables: RequireAtLeastOne ) => queryData.fetchMore({ query, updateQuery: (previousResults, { fetchMoreResult }) => { if (!fetchMoreResult) { return previousResults; } return mergeFunc(previousResults, fetchMoreResult); }, variables: { ...variables, ...extraVariables } }); if ( !queryData.loading && require && queryData.data && !require.reduce((acc, key) => acc && queryData.data[key] !== null, true) ) { dispatchAppState({ payload: { error: "not-found" }, type: "displayError" }); } return { ...queryData, loadMore }; } return useQuery; } export default makeQuery;