问题描述
我正在尝试用于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纪念组件,以避免不必要的重新渲染此组件
问题描述
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