-1

[EDIT] See my answer below.

In our react-native app, we're using GraphQL Code Generator (GCG) to generate GraphQL queries and mutations from our schema and local GraphQL files. Below is the generates section of our codegen.yml file.

generates:
  src/generated/graphql.tsx:
    plugins:
      - "typescript"
      - "typescript-operations"
      - "typescript-react-apollo"
    config:
      withResultType: true
      withHOC: false
      withHooks: true
      withComponent: false
      withMutationFn: false
  ./graphql.schema.json:
    plugins:
      - "introspection"

Queries are very straightforward in how they are called and data is accessed.

Mutations, however, have become a blocker for us.

Here is the graphql that GraphQL Code Generator is processing:

  mutation GetPaymentUrl(
    $account_number: String!
    $role: String!
    $pay_my_bill: Boolean
    $mortgageeBillIndicator: Boolean
    $requested_by: String!
  ) {
    getIncPaymentUrl(
      input: {
        account_number: $account_number
        role: $role
        pay_my_bill: $pay_my_bill
        mortgageeBillIndicator: $mortgageeBillIndicator
        requested_by: $requested_by
      }
    ) {
      account_number
      payment_portal_redirect_url
    }
  }

Here is the code generated by GCG:

export type Mutation = {
  __typename?: 'Mutation';
  getIncPaymentUrl?: Maybe<IncResponse>;
};

export type MutationGetIncPaymentUrlArgs = {
  input?: Maybe<IncPaymentRequestUrl>;
};

export type IncPaymentRequestUrl = {
  account_number: Scalars['String'];
  role: Scalars['String'];
  pay_my_bill?: Maybe<Scalars['Boolean']>;
  mortgageeBillIndicator?: Maybe<Scalars['Boolean']>;
  requested_by: Scalars['String'];
};

export type IncResponse = {
  __typename?: 'IncResponse';
  account_number?: Maybe<Scalars['String']>;
  payment_portal_redirect_url?: Maybe<Scalars['String']>;
};

export type GetPaymentUrlMutationVariables = Exact<{
  account_number: Scalars['String'];
  role: Scalars['String'];
  pay_my_bill?: Maybe<Scalars['Boolean']>;
  mortgageeBillIndicator?: Maybe<Scalars['Boolean']>;
  requested_by: Scalars['String'];
}>;

export type GetPaymentUrlMutation = {__typename?: 'Mutation'} & {
  getIncPaymentUrl?: Maybe<
    {__typename?: 'IncResponse'} & Pick<
      IncResponse,
      'account_number' | 'payment_portal_redirect_url'
    >
  >;
};

export const GetPaymentUrlDocument = gql`
  mutation GetPaymentUrl(
    $account_number: String!
    $role: String!
    $pay_my_bill: Boolean
    $mortgageeBillIndicator: Boolean
    $requested_by: String!
  ) {
    getIncPaymentUrl(
      input: {
        account_number: $account_number
        role: $role
        pay_my_bill: $pay_my_bill
        mortgageeBillIndicator: $mortgageeBillIndicator
        requested_by: $requested_by
      }
    ) {
      account_number
      payment_portal_redirect_url
    }
  }
`;

/**
 * __useGetPaymentUrlMutation__
 *
 * To run a mutation, you first call `useGetPaymentUrlMutation` within a React component and pass it any options that fit your needs.
 * When your component renders, `useGetPaymentUrlMutation` returns a tuple that includes:
 * - A mutate function that you can call at any time to execute the mutation
 * - An object with fields that represent the current status of the mutation's execution
 *
 * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
 *
 * @example
 * const [getPaymentUrlMutation, { data, loading, error }] = useGetPaymentUrlMutation({
 *   variables: {
 *      account_number: // value for 'account_number'
 *      role: // value for 'role'
 *      pay_my_bill: // value for 'pay_my_bill'
 *      mortgageeBillIndicator: // value for 'mortgageeBillIndicator'
 *      requested_by: // value for 'requested_by'
 *   },
 * });
 */
export function useGetPaymentUrlMutation(
  baseOptions?: Apollo.MutationHookOptions<
    GetPaymentUrlMutation,
    GetPaymentUrlMutationVariables
  >,
) {
  return Apollo.useMutation<
    GetPaymentUrlMutation,
    GetPaymentUrlMutationVariables
  >(GetPaymentUrlDocument, baseOptions);
}
export type GetPaymentUrlMutationHookResult = ReturnType<
  typeof useGetPaymentUrlMutation
>;
export type GetPaymentUrlMutationResult = Apollo.MutationResult<GetPaymentUrlMutation>;
export type GetPaymentUrlMutationOptions = Apollo.BaseMutationOptions<
  GetPaymentUrlMutation,
  GetPaymentUrlMutationVariables
>;

When I examine getPaymentUrlMutation from my example above, I don't see the mutate function documented in the generated code. I do see "call", "apply", and "bind" methods.

I'm not clear on where/how to call this mutation.

I've found that if I call getPaymentUrlMutation.call({}) before the return in my tsx file, I get an infinite loop of requests.

If I call it like the following in the return...

          <ButtonStyle
            onPress={() => {
              getPaymentUrlMutation.call({}).then((r) =>
                  OnPayment(
                    r.data?.getIncPaymentUrl?.payment_portal_redirect_url,
                  ),
                );
            }}>
            <PayButtonStyle>pay now</PayButtonStyle>
          </ButtonStyle>

... I don't have an opportunity to handle errors. Plus, as @xadm notes, it doesn't seem "right" from a react standpoint.

How should I execute the mutation in the context of an onPress event for a react-native button?

David Nedrow
  • 1,098
  • 1
  • 9
  • 26

1 Answers1

0

I finally figured out how to handle mutations generated by GraphQL Code Generator.

Here's what this looks like in my case:

<ButtonStyle
  onPress={() => {
    getVideoUrlMutation.then((r) => 
      OnPayment(r.data?.getIncPaymentUrl?.payment_portal_redirect_url));
  }}>
  <PayButtonStyle>pay now</PayButtonStyle>
</ButtonStyle>;

r being the object returned from the mutation.

[EDIT] I've received some negative feedback on my solution above, though I've talked to other react developers who say what I've done is exactly how it should be done. The yea's far outweigh the nay, and this works for me.

David Nedrow
  • 1,098
  • 1
  • 9
  • 26
  • very limited usage ... and it looks like you don't understand data-driven (not event-based) react nature – xadm Apr 01 '21 at 20:07
  • @xadm nice criticism. Care to educate me? As yet, you haven’t written anything about my original question which has to do with code generated by GraphQL Code Generator. – David Nedrow Apr 01 '21 at 20:10
  • I provided a link to apollo mutation docs, it should be enough – xadm Apr 01 '21 at 20:15
  • Unfortunately, the Apollo docs don’t address code generated by GraphQL Code Generator. – David Nedrow Apr 01 '21 at 20:16
  • I guess usage is exactly the same ... show generated code fragment? – xadm Apr 01 '21 at 20:24
  • I've updated my original question with more detail. – David Nedrow Apr 01 '21 at 22:30
  • this fragment `return Apollo.useMutation<` proves that I'm right ... and you don't need `.call` ... `getVideoUrlMutation().then((r) => ` should work, too – xadm Apr 01 '21 at 22:48
  • eh, I didn't write it can't/or won't work ... it's just not the optimal way to do it ... https://stackoverflow.com/a/59472340/6124657 ... in this case (on redirect) you can ignore loading states, error handling, redefining event handlers on every render ( https://flaviocopes.com/react-hook-usecallback/ ), etc. ... but it's worth to know f.e. `onCompleted` existence for more declarative/readable code https://stackoverflow.com/a/57733954/6124657 – xadm Apr 02 '21 at 19:22