apollographql / apollo-feature-requests

๐Ÿง‘โ€๐Ÿš€ Apollo Client Feature Requests | (no ๐Ÿ› please).
Other
130 stars 7 forks source link

Optional GraphQL documents in useQuery and useMutation #193

Open amannn opened 4 years ago

amannn commented 4 years ago

You can mark a query as optional by doing this:

useQuery(query, {skip: true});

However the query is still parsed and validated. I have a situation where a React component receives a query via an optional prop and I'm using skip if the prop is absent. This doesn't work however, as the validation still runs against the undefined query.

Since Hooks need to be called unconditionally, there's no reasonable way I can prevent the call to useQuery. As far as I can tell, the only good way to handle this would be by handling it inside react-apollo.

I've got the same situation for mutations as well and my component accepts quite a few queries and mutations. Moving them to conditional components results into callback madness with render props. Therefore it would be very valuable to somehow handle this with Hooks.

Here are my workarounds:

const mockQuery = gql`
  query {
    mock
  }
`;

function useOptionalQuery(query, options) {
  const result = useQuery(options.skip ? mockQuery : query, options);
  return options.skip ? undefined : result;
}

const mockMutation = gql`
  mutation {
    mock
  }
`;

function useOptionalMutation(mutation, options) {
  const result = useMutation(options.skip ? mockMutation : mutation, options);

  const onExecute = () => {
    throw new Error(
      "This mutation was marked with `skip`, it's not possible to call it."
    );
  };

  return options.skip ? [onExecute] : result;
}

I guess the most interesting question is what you return in this case. It might make sense to use separate hooks for this, as otherwise the type definition of the result from useQuery would require the consumer to always add null checks if you use TypeScript.

What do you think?

Soni96pl commented 3 years ago

Thanks @amannn, this really helped us. Calling effects conditionally is not always an option (which is why skip exists) and Apollo is evaluating mutations eagerly even with skip causing them to crash when none exist. This is a valid case such as when using higher order components that provide child with a set of mutations, utility functions and data. Could we perhaps get someone to look at this again? ๐Ÿ™‚