Fix types

This commit is contained in:
dominik-zeglen 2019-08-12 13:48:09 +02:00
parent 2f7867bf99
commit ebd4f3093c
2 changed files with 75 additions and 105 deletions

View file

@ -1,19 +1,14 @@
import { ApolloError } from "apollo-client";
import { ApolloError, MutationUpdaterFn } from "apollo-client";
import { DocumentNode } from "graphql";
import React from "react";
import {
Mutation,
MutationFn,
MutationResult,
MutationUpdaterFn
} from "react-apollo";
import { Mutation, MutationFunction, MutationResult } from "react-apollo";
import useNotifier from "./hooks/useNotifier";
import i18n from "./i18n";
export interface TypedMutationInnerProps<TData, TVariables> {
children: (
mutateFn: MutationFn<TData, TVariables>,
mutateFn: MutationFunction<TData, TVariables>,
result: MutationResult<TData>
) => React.ReactNode;
onCompleted?: (data: TData) => void;
@ -21,26 +16,17 @@ export interface TypedMutationInnerProps<TData, TVariables> {
variables?: TVariables;
}
// For some reason Mutation returns () => Element instead of () => ReactNode
export function TypedMutation<TData, TVariables>(
mutation: DocumentNode,
update?: MutationUpdaterFn<TData>
) {
class StrictTypedMutation extends Mutation<TData, TVariables> {}
return (props: TypedMutationInnerProps<TData, TVariables>) => {
const notify = useNotifier();
// Obviously, this is workaround to the problem described here:
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/32588
const {
children,
onCompleted,
onError,
variables
} = props as JSX.LibraryManagedAttributes<
typeof StrictTypedMutation,
typeof props
>;
const { children, onCompleted, onError, variables } = props;
return (
<StrictTypedMutation
<Mutation
mutation={mutation}
onCompleted={onCompleted}
onError={err => {
@ -55,8 +41,8 @@ export function TypedMutation<TData, TVariables>(
variables={variables}
update={update}
>
{children}
</StrictTypedMutation>
{(mutateFn, result) => <>{children(mutateFn, result)}</>}
</Mutation>
);
};
}

View file

@ -1,9 +1,9 @@
import { ApolloQueryResult } from "apollo-client";
import { DocumentNode } from "graphql";
import gql from "graphql-tag";
import React from "react";
import { Query, QueryResult } from "react-apollo";
import { ApolloQueryResult } from "apollo-client";
import AppProgress from "./components/AppProgress";
import ErrorPage from "./components/ErrorPage/ErrorPage";
import useNavigator from "./hooks/useNavigator";
@ -62,98 +62,82 @@ class QueryProgress extends React.Component<QueryProgressProps, {}> {
}
}
// For some reason Query returns () => Element instead of () => ReactNode
export function TypedQuery<TData, TVariables>(
query: DocumentNode
): React.FC<TypedQueryInnerProps<TData, TVariables>> {
class StrictTypedQuery extends Query<TData, TVariables> {}
return props => {
return ({ children, displayLoader, skip, variables, require }) => {
const navigate = useNavigator();
const pushMessage = useNotifier();
return (
<AppProgress>
{({ setProgressState }) => {
// Obviously, this is workaround to the problem described here:
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/32588
const {
children,
displayLoader,
skip,
variables,
require
} = props as JSX.LibraryManagedAttributes<
typeof StrictTypedQuery,
typeof props
>;
return (
<StrictTypedQuery
fetchPolicy="cache-and-network"
query={query}
variables={variables}
skip={skip}
context={{ useBatching: true }}
>
{queryData => {
if (queryData.error) {
const msg = i18n.t("Something went wrong: {{ message }}", {
message: queryData.error.message
});
pushMessage({ text: msg });
}
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 }
});
let childrenOrNotFound = children({
...queryData,
loadMore
{({ setProgressState }) => (
<Query
fetchPolicy="cache-and-network"
query={query}
variables={variables}
skip={skip}
context={{ useBatching: true }}
>
{queryData => {
if (queryData.error) {
const msg = i18n.t("Something went wrong: {{ message }}", {
message: queryData.error.message
});
if (
!queryData.loading &&
require &&
queryData.data &&
!require.reduce(
(acc, key) => acc && queryData.data[key] !== null,
true
)
) {
childrenOrNotFound = (
<ErrorPage onBack={() => navigate("/")} />
);
}
pushMessage({ text: msg });
}
if (displayLoader) {
return (
<QueryProgress
loading={queryData.loading}
onCompleted={() => setProgressState(false)}
onLoading={() => setProgressState(true)}
>
{childrenOrNotFound}
</QueryProgress>
);
}
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 }
});
return childrenOrNotFound;
}}
</StrictTypedQuery>
);
}}
let childrenOrNotFound = children({
...queryData,
loadMore
});
if (
!queryData.loading &&
require &&
queryData.data &&
!require.reduce(
(acc, key) => acc && queryData.data[key] !== null,
true
)
) {
childrenOrNotFound = <ErrorPage onBack={() => navigate("/")} />;
}
if (displayLoader) {
return (
<QueryProgress
loading={queryData.loading}
onCompleted={() => setProgressState(false)}
onLoading={() => setProgressState(true)}
>
{childrenOrNotFound}
</QueryProgress>
);
}
return <>{childrenOrNotFound}</>;
}}
</Query>
)}
</AppProgress>
);
};