在渲染道具中使用apollo graphql.的方式。我曾经能够做到这一点:
export const CsmartQuery = (({ children, isShowGenericErrorSnackBarForError, ...rest }) => (
<Query errorPolicy="all"
{...rest} >
{result =>
<GraphQLErrorHandler isShowGenericErrorSnackBarForError={isShowGenericErrorSnackBarForError}
result={result}>
{(transformedResult) => children(transformedResult)}
</GraphQLErrorHandler>
}
</Query>
))
我的 GraphQLErrorHandler,用于检查错误,如果它是服务器错误(我的通用捕获所有错误(,那么我会向用户显示一个错误小吃栏。我还处理错误,去除所有不需要的东西,只向孩子们发送代码和消息。这是完整的 GraphQLErrorHandler 组件
import React from 'react';
import { showErrorSnackBarAction } from '../redux/appActions'
import { connect } from 'react-redux'
const transformError = (e) => {
if(e.networkError ||
((e.graphQLErrors || []).length === 0) ||
!e.graphQLErrors[0].extensions ||
e.graphQLErrors[0].extensions.code === 'SERVER_ERROR') {
return {
message: 'An error occurred while processing your request. Please try again',
code: 'SERVER_ERROR'
}
}
return {
message: e.graphQLErrors[0].message,
code: e.graphQLErrors[0].extensions.code,
}
};
const transformErrorsInResult = (result) => {
return {...result, error: result.error ? transformError(result.error) : undefined}
}
const GraphQLErrorHandler = ({result, isShowGenericErrorSnackBarForError, showErrorSnackBarAction, children}) => {
const [transformedResult, setTransformedResult] = React.useState(transformErrorsInResult(result))
React.useEffect(() => {
const newResult = transformErrorsInResult(result)
if(newResult.error && isShowGenericErrorSnackBarForError) {
showErrorSnackBarAction({message: newResult.error.message})
}
setTransformedResult(() => newResult)
}, [result, isShowGenericErrorSnackBarForError, showErrorSnackBarAction])
return (
children(transformedResult)
)
}
export default connect(null, { showErrorSnackBarAction })(GraphQLErrorHandler);
而且我不使用来自 apollo 的 Query,而是在任何地方使用 CsmartQuery 组件。
<CsmartQuery query={companyAddressQuery} variables={{ companyId: company.id }} isShowGenericErrorSnackBarForError>
{({ data, loading, error }) => {
if (error) return null
if (loading)
return (
<Container textAlign="center">
<Loader active />
</Container>
)
return <AddressDetailsWrapper companyAddresses={data.companyAddresses || []} company={company} {...rest} />
}}
</CsmartQuery>
如何使用 useQuery 钩子并能够以通用方式处理错误?如果需要,我希望转换错误并显示小吃店。最好是我不必在每个组件中重复代码。
这就是我登陆时要做的事情。创建了一个包裹所有阿波罗钩子的自定义钩子
export const useCsmartQuery = (query, queryVariables, isShowGenericErrorSnackBarForError = true) => {
const queryResult = useQuery(query, queryVariables)
const { error } = queryResult
const dispatch = useDispatch()
if (error) {
const transformedError = transformError(error)
if (isShowGenericErrorSnackBarForError) {
dispatch(showErrorSnackBarAction({ message: transformedError.message }))
}
}
return queryResult
}
export const useCsmartMutation = (mutation, mutationData, isShowGenericErrorSnackBarForError = true) => {
const [callMutation, mutationResult] = useMutation(mutation, mutationData)
const { error } = mutationResult
const dispatch = useDispatch()
if (error) {
const transformedError = transformError(error)
if (isShowGenericErrorSnackBarForError) {
dispatch(showErrorSnackBarAction({ message: transformedError.message }))
}
return [callMutation, {...mutationResult, error: transformedError }]
}
return [callMutation, mutationResult]
}
现在在任何地方使用自定义钩子。