简体   繁体   中英

onError in GraphQL mutations

I was trying onError for graphql mutations and realised that they don't work properly:

https://github.com/apollographql/apollo-client/issues/5708

What else can be done for catching errors then? In a previous question, I was told that using try catch blocks for mutations is not a good idea.

I am trying to do something like this, with a possible workaround:

I ask user for an input, then run a query. Depending on the results of the query, I render some User components. From the user component, I use the button to run mutations.

export const AddContact: React.FunctionComponent = () => {
  const initialValues: FormValues = {
    phoneNumber: '',
  };

  const [isSubmitted, setIsSubmitted] = useState(false);
  const [userData, setUserData] = useState<UsersLazyQueryHookResult>('');
  const navigation = useNavigation();
  const validationSchema = phoneNumberValidationSchema;

  const _onLoadUserError = React.useCallback((error: ApolloError) => {
    Alert.alert('Unable to Add Contact');
  }, []);

  const [
    createUserRelationMutation,
    {
      data: addingContactData,
      loading: addingContactLoading,
      error: addingContactError,
      called: isMutationCalled,
    },
  ] = useCreateUserRelationMutation({
    onCompleted: () => {
      Alert.alert('Contact Added');
    },
  });


    const onAddContact = (id: number) => {
    setIsSubmitted(false);
    setUserData(null);
    createUserRelationMutation({
      variables: {
        input: { relatedUserId: id, type: RelationType.Contact, userId: 1 },
      },
    });
  }

  const getContactId = React.useCallback(
    (data: UsersLazyQueryHookResult) => {
      if (data) {
        if (data.users.nodes.length == 0) {
          Alert.alert('No User Found');
        } else {
          setUserData(data);
        }
      }
    },
    [onAddContact],
  );

  const [loadUsers] = useUsersLazyQuery({
    onCompleted: getContactId,
    onError: _onLoadUserError,
  });

  const handleSubmitForm = React.useCallback(
    (values: FormValues, helpers: FormikHelpers<FormValues>) => {
      setIsSubmitted(true);
      const plusSign = '+';
      const newPhoneNumber = plusSign.concat(values.phoneNumber);
      console.log('Submitted');
      loadUsers({
        variables: {
          where: { phoneNumber: newPhoneNumber },
        },
      });
      helpers.resetForm();
    },
    [loadUsers],
  );


    if (!addingContactLoading && isMutationCalled) {
    if (addingContactError) {
      console.log('this is the error', addingContactError);
      if ((addingContactError.toString()).includes('already exists')){
        Alert.alert('Contact Already Exists');
      }
      else{
      Alert.alert('Unable to Add Contact');
      }
    }
  }

  return (
...
)
 <User onAddContact={onAddContact} data={userData}></User>
...
export const User: React.FunctionComponent<UserProps> = ({
  data,
  onAddContact,
}) => {
  if (!data) return null;
  return (
                <Button
                  onPress={() => onAddContact(Number(item.id))}
                  >
                </Button>

Generally the process works fine but when's there's a Alert.alert('Contact Already Exists'); error in the mutation, it creates a problem. For instance, after I close the error alert, and run a new query, I am supposed to get only the new User component (even though I am only running a query now, not a mutation). However, I also get the Contact Already Added alert. In fact it pops up twice.

Maybe the problem is in the callbacks.

Using a.catch like this would work but is there no other way to do this? Since I am not using catch for the query, the code would become inconsistent.

.catch((err: any) => {
      console.log('errror', err)
      if ((err.toString()).includes('already exists')){
        console.log('working')
        Alert.alert('Contact Already Exists');
      }
      else{
      Alert.alert('Unable to Add Contact');
      }
    });

You could use onError callback instead of checking for addingContactError property from the result directly on function body like shown below

const _onCreateUserRelationError = React.useCallback((error: ApolloError) => {
    console.log('this is the error', error);
    Alert.alert(error.message.includes('already exists') ? 'Contact Already Exists' : 'Unable to Add Contact');
}, []);

const [
    createUserRelationMutation,
    {
        data: addingContactData,
        loading: addingContactLoading,
        called: isMutationCalled,
    },
] = useCreateUserRelationMutation({
    onCompleted: () => {
        Alert.alert('Contact Added');
    },
    onError: _onCreateUserRelationError
});

Note: Memoize the component using React.memo to avoid unnecessary re-rendering of this component

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM