Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The mutation result returned when useMutation mutate function resolves with errors does not return an ApolloError on error property, but an errors array #7913

Open
baseten opened this issue Mar 28, 2021 · 1 comment
Labels
🔍 investigate Investigate further

Comments

@baseten
Copy link

baseten commented Mar 28, 2021

Intended outcome:

When reading the mutation result from the resolved promise of a useMutation mutate function (when errorPolicy is all) the format of the result should be consistent with that of the useMutation hook itself and as the documentation describes under "Mutation result".

Actual outcome:

A vanilla mutation result object is actually returned with an empty data Object and an errors array, rather than an ApolloError on an error key:

https://github.com/apollographql/apollo-client/blob/main/src/core/QueryManager.ts#L207

useMutation's update callback is also called with this same object:

https://github.com/apollographql/apollo-client/blob/main/src/core/QueryManager.ts#L307

However, the error property returned from useMutation is returned correctly.

How to reproduce the issue:

In our particular use case, we can't use the error returned from useMutation as we are calling the mutate function in a Formik onSubmit callback and need access to Formik's setErrors function:

// This error is correctly an ApolloError, but not helpful in terms of supplying to `setErrors`
const [mutateSomething, {error}] = useMutation(mutation, { 
  errorPolicy: 'all',
  update(cache, mutationResult) {
    // I'd expect this to be an ApolloError on error key
    const { errors, data } = mutationResult;
    if(errors) return;
    // do cache update...
  },
  onCompleted(data) {
    // Annoyingly this doesn't have access to error or errors, so to bail early we have to check if data is empty
    if(isEmpty(data)) return;
    // do completed stuff...
  }
});

const handleFormikSubmit = useCallback(
  async (values, { setErrors }) => {
    // This errors array is correct, but I'd expect it to be an ApolloError on error key
    const { errors } = await mutateSomething({
      variables: {
        // transform values to input...
      }
    });
    // parse validation errors and pass them to setErrors...
  },
  [mutateSomething],
);

Versions

System:
OS: macOS 11.1
Binaries:
Node: 10.15.3 - ~/.nvm/versions/node/v10.15.3/bin/node
Yarn: 1.19.1 - /usr/local/bin/yarn
npm: 6.4.1 - ~/.nvm/versions/node/v10.15.3/bin/npm
Browsers:
Chrome: 89.0.4389.90
Firefox: 86.0.1
Safari: 14.0.2
npmPackages:
@apollo/client: ^3.2.0 => 3.2.0
@apollo/link-error: ^2.0.0-beta.3 => 2.0.0-beta.3

@baseten baseten changed the title mutation result returned when useMutation mutate function resolves with errors, does not return an ApolloError on error property but an errors array The mutation result returned when useMutation mutate function resolves with errors does not return an ApolloError on error property, but an errors array Mar 30, 2021
@jcreighton jcreighton self-assigned this Apr 21, 2021
@brainkim brainkim self-assigned this Jun 22, 2021
@brainkim brainkim mentioned this issue Aug 16, 2021
14 tasks
@hwillson hwillson added the 🔍 investigate Investigate further label May 31, 2022
@baseten
Copy link
Author

baseten commented Aug 24, 2023

It looks like this is because rather than the mutation function returning an ApolloQueryResult<TData>, it returns a FetchResult which in turn extends the upstream graphql type ExecutionResult (containing an errors key of ReadonlyArray<GraphQLError>), but obviously missing the error?: ApolloError.

It looks like you added a TODO about this in your types 😄

export type MutationTuple<
TData,
TVariables,
TContext = DefaultContext,
TCache extends ApolloCache<any> = ApolloCache<any>
> = [
(
options?: MutationFunctionOptions<TData, TVariables, TContext, TCache>
// TODO This FetchResult<TData> seems strange here, as opposed to an
// ApolloQueryResult<TData>
) => Promise<FetchResult<TData>>,
MutationResult<TData>
];

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔍 investigate Investigate further
Projects
None yet
Development

No branches or pull requests

4 participants