GraphQL突变中的onError[英] onError in GraphQL mutations

本文是小编为大家收集整理的关于GraphQL突变中的onError的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我正在尝试用于GraphQl突变的OnError,并意识到它们无法正常工作:

那么,捕获错误还能做什么?在上一个问题中,有人告诉我,使用尝试捕获块进行突变不是一个好主意.

我正在尝试这样做的事情,并可能解决:

我询问用户输入,然后运行查询.根据查询的结果,我呈现一些User组件.从用户组件中,我使用该按钮运行突变.

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>

通常,该过程正常工作,但是当突变中有一个Alert.alert('Contact Already Exists');错误时,它会产生问题.例如,在关闭错误警报并运行新查询后,我应该只能获得新的用户组件(即使我现在只运行查询,而不是突变).但是,我也获得了Contact Already Added警报.实际上,它弹出了两次.

也许问题在回调中.

使用这样的捕获可以工作,但是没有其他方法可以做到吗?由于我不在查询中使用捕获,因此代码会变得不一致.

.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');
      }
    });

推荐答案

您可以使用onError回调,而不是直接从功能体上的结果检查addingContactError属性,如下所示

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
});

注意:使用React.memo纪念组件,以避免不必要的重新渲染此组件

本文地址:https://www.itbaoku.cn/post/1938039.html

问题描述

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 Usercomponents. 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 Addedalert. 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