Previously, I defined mutations as:
import { Mutation, MutationFn } from 'react-apollo'
interface ContainerProps {
updateSaveStatus: MutationFn<updateSaveStatusMutation, updateSaveStatusMutationVariables>
}
class UpdateSaveStatusMutation extends Mutation<
updateSaveStatusMutation,
updateSaveStatusMutationVariables
> {}
render() {
<UpdateSaveSatusMutation mutation={UPDATE_SAVE_STATUS}>
{(updateSaveStatus) => (
<Container updateSaveStatus={updateSaveStatus} />
)}
</UpdateSaveStatusMutation>
and all was good. However, it appears that MutationFn was recently removed (perhaps in response to this: https://github.com/apollographql/react-apollo/issues/1975 ?).
MutationFunc would seem to be the correct replacement, however it does not seem to be compatible with the child of the mutation function:
Types of property 'updateSaveStatus' are incompatible.
Type '(options?: MutationOptions<updateSaveStatusMutation, updateSaveStatusMutationVariables> | undefin...' is not assignable to type 'MutationFunc<updateSaveStatusMutation, updateSaveStatusMutationVariables>'.
Type 'Promise<void | FetchResult<Record<string, any>, Record<string, any>>>' is not assignable to type 'Promise<ApolloQueryResult<updateSaveStatusMutation>>'.
Type 'void | FetchResult<Record<string, any>, Record<string, any>>' is not assignable to type 'ApolloQueryResult<updateSaveStatusMutation>'.
Type 'void' is not assignable to type 'ApolloQueryResult<updateSaveStatusMutation>'.
It appears that what used to be called MutationFn is now defined implicitly as:
children: (mutateFn: (options?: MutationOptions<TData, TVariables>) => Promise<void | FetchResult>, result: MutationResult<TData>) => React.ReactNode
What is the new correct type to give to the children of a Mutation component? If there isn't one, can we have MutationFn back? Or, even better, make the types consistent (the possible void in MutationFn is superfluous from what I can tell and it would be good for it to go)?
Version
I'm confused: When can a MutationFn return a promise that is resolved with void?
This forces me to do things like this:
private handleFormSubmit = async (
login: MutationFn<ILoginMutation, ILoginMutationVariables>,
values: ILoginFormValues,
actions: FormikActions<ILoginFormValues>
) => {
try {
const result = await login({ variables: values })
if (result) {
localStorage.setItem(AUTH_TOKEN, result.data!.login.token)
this.props.history.push('/')
} else {
// WTF. Help plx! When can this happen? What do i do?!?
}
} catch (error) {
handleSubmitError(error, actions)
}
}
+1 for void question
@codepunkt Did you find out a solution?
@sublimeye #2095 it seems it cannot be void if onError is not provided.
it remains a bug IMO since the typing is not optimal. However, we rewrite our MutationFn without void since we don't use onError
@eltonio450 mind sharing your new MutationFn implementation in a gist? Running into this exact issue today.
Ok, honestly not proud of our code, but we basically changed the type to OvrseaMutationFn
// we deleted the void: https://github.com/apollographql/react-apollo/issues/2095 (resp: Sinane)
export type OvrseaMutationFn<DataType = any, Variables = OperationVariables> = (options?: MutationOptions<DataType, Variables>) => Promise<FetchResult<DataType>>;
export type InjectedMutationResults<Name extends string, DataType> = {
[x in Name]: {
mutation: OvrseaMutationFn<DataType>,
result: MutationResult<DataType>,
}
}
Then, we use 'as' to type our injected elements in our HOC:
<Mutation
{...config}
context={context}
optimisticResponse={optimisticResponse} //can be overwritten by mutate
>
{(mutation: MutationFn<DataType, Variables>, result: MutationResult<DataType>) => {
const injectedElements = {
[config.name as Name]: {
mutation,
result,
},
} as InjectedMutationResults<Name, DataType>;
return (
<WrappedComponent
{...this.props}
{...injectedElements}
/>
);
}
}
</Mutation>
Let me know if it's not clear. This part is not stable yet, so the whole file is still messy (+ we are waiting for the React hooks to really deep dive this topic). If you are really interested, I can also post it here. We kinda rebuild a HOC for queries from the Mutation component bc apollo is pushing for the Mutation component and doc of connected comp disappears (https://github.com/apollographql/apollo-client/issues/3253)
@eltonio450 thanks a lot for sharing this.
It's a shame it's such a mess to avoid that - I think I'll just have to do data! and trust that it's not void on the mutation promise result until the types are updated.
Closing as duplicate of #2095. The discussion there describes the issue more clearly.
Most helpful comment
I'm confused: When can a
MutationFnreturn a promise that is resolved withvoid?This forces me to do things like this: