Обработка ошибок с помощью реакции-аполлона

10

Я пытался разобраться в этой проблеме, но не нашел сильного ответа на нее. Я пытаюсь выполнить мутацию входа в систему с помощью ловушки useMutation.

TLDR; Я хочу знать, в чем именно разница между ошибкой onError, переданной в параметрах, и ошибкой, переданной мне useMutation

Вот мой фрагмент кода

const [login, { data, loading, error }] = useMutation(LOGIN_QUERY, {
        variables: {
            email,
            password
        },
        onError(err) {
            console.log(err);
        },
});

На стороне сервера у меня есть предустановленное / жестко закодированное письмо, используемое для входа в систему, и я не использую Apollo или любой другой клиент. В обработчике этой Мутации входа я просто выкидываю ошибку, если адрес электронной почты не совпадает, используя

throw new Error('Invalid Email');

Теперь я хочу обработать эту ошибку на стороне клиента (React). Но меня беспокоит то, что если я использую «ошибку», возвращенную из ловушки useMutation, и пытаюсь показать ошибку таким образом

render() {
...
{error && <div> Error occured </div>}
...
}

ошибка обновляется в пользовательском интерфейсе, но затем сразу же React показывает мне экран с необработанным отклонением (ошибка): ошибка Graphql: My-custom-error-message

Но, если я использую onError, переданный в параметрах для использования функцииMutate, то этот экран мне не показывается, и я могу сделать все, что захочу, с ошибкой.

Я хочу знать, в чем именно разница между onError, передаваемым в опциях, и ошибкой, переданной мне useMutation, и почему React показывает мне этот экран ошибок, когда onError не используется.

Спасибо!

d_bhatnagar
источник

Ответы:

33

Через API-интерфейс Apollo предоставляет два вида ошибок: ошибки GraphQL , которые возвращаются как часть ответа errors, dataа также сетевые ошибки, возникающие при сбое запроса. Сетевая ошибка возникает, когда не удается связаться с сервером, или если состояние ответа не равно 200 - запросы, которые имеют errorsв ответе, могут по-прежнему иметь статус 200. Но недопустимый запрос, например, приведет к статус 400 и ошибка сети в клиенте Apollo.

Apollo Client фактически предоставляет четыре различных способа обработки ошибок мутации:

1.) Вызов mutateфункции, возвращаемой ловушкой, возвращает Promise. Если запрос выполнен успешно, Promise преобразуется в объект ответа, который включает в себя dataвозвращенный сервером. В случае сбоя запроса Обещание будет отклонено с ошибкой. Вот почему вы видите сообщение «Unhandled Rejection» в консоли - вам нужно обработать отклоненное обещание.

login()
  .then(({ data }) => {
    // you can do something with the response here
  })
  .catch(e => {
    // you can do something with the error here
  })

или с синтаксисом async / await:

try {
  const { data } = await login()
} catch (e) {
  // do something with the error here
}

По умолчанию Promise будет отклонять либо ошибки GraphQL, либо ошибки сети. Установив errorPolicy к ignoreили all, хотя, обещание будет только отказаться от сетевых ошибок. В этом случае ошибки GraphQL будут по-прежнему доступны через объект ответа, но Обещание разрешится.

2.) Единственное исключение из вышеперечисленного возникает, когда вы предоставляете onErrorфункцию. В этом случае Обещание всегда будет разрешаться, а не отклоняться, но если возникнет ошибка, onErrorбудет вызвана полученная ошибка. errorPolicyУстановить применяется здесь - onErrorвсегда будет вызываться для сетевых ошибок , но будет вызываться только с ошибками GraphQL при использовании по умолчанию errorPolicyв none. Использование onErrorэквивалентно перехвату отклоненного Promise - оно просто перемещает обработчик ошибок с сайта вызова mutateфункции на сайт вызова ловушки.

3.) В дополнение к mutateфункции useMutationловушка также возвращает объект результата. Этот объект также отображает любые ошибки, возникающие при запуске мутации. В отличие от функций обработчика ошибок, которые мы написали выше, этот errorобъект представляет состояние приложения . И объекты, errorи dataобъекты, представленные таким образом, существуют для удобства. Они эквивалентны выполнению этого:

const [mutate] = useMutation(YOUR_MUTATION)
const [data, setData] = useState()
const [error, setError] = useState()
const handleClick = async () => {
  try {
    const { data } = await mutate()
    setData(data)
  catch (e) {
    setError(e)
  }
}

Такое состояние ошибки может быть полезно, если вы хотите, чтобы ваш пользовательский интерфейс отражал тот факт, что есть ошибка. Например, вы можете изменить цвет элемента, пока мутация не пройдет без ошибки. Вместо того, чтобы писать вышеприведенный шаблон самостоятельно, вы можете просто использовать предоставленный объект результата.

const [mutate, { data, error }] = useMutation(YOUR_MUTATION)

ПРИМЕЧАНИЕ. Хотя вы можете использовать выставленное состояние ошибки для обновления пользовательского интерфейса, это не заменяет фактическую обработку ошибки. Вы должны либо предоставить onErrorобратный вызов, либо catchошибку, чтобы избежать предупреждений о необработанном отказе от обещания.

4.) Наконец, вы также можете использовать apollo-link-error, чтобы добавить глобальную обработку ошибок для ваших запросов. Это позволяет, например, отображать диалоговое окно с сообщением об ошибке независимо от того, где в вашем приложении возник запрос.

Какой из этих методов вы используете в своем приложении, сильно зависит от того, что вы пытаетесь сделать (глобальный против локального, состояние против обратного вызова и т. Д.). В большинстве приложений будет использоваться более одного метода обработки ошибок.

Даниэль Реарден
источник
Спасибо за объяснение ! Проголосовал!
Hyphæne Ohmen
Потрясающее и исчерпывающее объяснение. Вы заработали высокий голос.
Дэвид Фернандес