Распространенный способ обработки ошибок в Graphql с помощью хуков - PullRequest
0 голосов
/ 20 сентября 2019

В способе рендеринга реквизита для работы с 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);

И я не использую Query from apollo и везде использую компонент 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 и иметь возможность обрабатывать ошибки общим способом?Я хотел бы, чтобы ошибка трансформировалась, а при необходимости показывался снэк-бар.Желательно, чтобы мне не приходилось повторять код в каждом компоненте.

1 Ответ

0 голосов
/ 28 сентября 2019

Это то, чем я занимался.Создан пользовательский хук, который оборачивает все хуки apollo

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]
}

Теперь используйте пользовательские хуки везде.

...