saleor-dashboard/src/hooks/makeQuery.ts

116 lines
2.9 KiB
TypeScript
Raw Normal View History

2019-11-14 14:37:32 +00:00
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<TData, TVariables> {
loadMore: (
mergeFunc: (prev: TData, next: TData) => TData,
extraVariables: Partial<TVariables>
) => Promise<ApolloQueryResult<TData>>;
}
2019-11-19 11:31:32 +00:00
export type UseQueryResult<TData, TVariables> = QueryResult<TData, TVariables> &
2019-11-14 14:37:32 +00:00
LoadMore<TData, TVariables>;
type UseQueryOpts<TData, TVariables> = Partial<{
displayLoader: boolean;
require: Array<keyof TData>;
skip: boolean;
variables: TVariables;
}>;
type UseQueryHook<TData, TVariables> = (
opts: UseQueryOpts<TData, TVariables>
2019-11-19 11:31:32 +00:00
) => UseQueryResult<TData, TVariables>;
2019-11-14 14:37:32 +00:00
function makeQuery<TData, TVariables>(
query: DocumentNode
): UseQueryHook<TData, TVariables> {
function useQuery<TData, TVariables>({
displayLoader,
require,
skip,
variables
2019-11-19 11:31:32 +00:00
}: UseQueryOpts<TData, TVariables>): UseQueryResult<TData, TVariables> {
2019-11-14 14:37:32 +00:00
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<TVariables>
) =>
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;