Błędy obsługi przy użyciu aplikacji respons-apollo Hak mutacji

10

Próbowałem obejść ten problem, ale nie znalazłem na to silnej odpowiedzi. Próbuję wykonać mutację logowania przy użyciu haka useMutation.

TLDR; Chcę wiedzieć, jaka dokładnie jest różnica między onError przekazywanym w opcjach a błędem podanym mi przez useMutation

Oto mój fragment kodu

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

Po stronie serwera mam wstępnie ustawiony / zakodowany e-mail używany do logowania i nie używam Apollo ani żadnego innego klienta. W rozwiązaniu tej mutacji logowania po prostu rzucam błąd, jeśli wiadomość e-mail nie jest taka sama

throw new Error('Invalid Email');

Teraz chcę obsłużyć ten błąd po stronie klienta (React). Obawiam się jednak, że jeśli użyję „błędu” zwróconego z haka useMutation i spróbuję pokazać błąd w ten sposób

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

błąd jest aktualizowany w interfejsie użytkownika, ale natychmiast React pokazuje mi ekran z nieobsługiwanym odrzuceniem (błąd): Błąd Graphql: komunikat o błędzie My-custom-error

Ale jeśli użyję onError przekazanego w opcjach funkcji useMutate, to nie pokaże mi tego ekranu i mogę zrobić co tylko chcę z błędem.

Chcę wiedzieć, jaka dokładnie jest różnica między onError przekazywanym w opcjach a błędem podanym przez useMutation i dlaczego React pokazuje mi ten ekran błędu, gdy onError nie jest używany.

Dzięki!

d_bhatnagar
źródło

Odpowiedzi:

32

Apollo eksponuje dwa rodzaje błędów poprzez jego API: GraphQL błędy , które są zwracane jako część odpowiedzi, jak errorsobok datai błędów w sieci , które występują, gdy wniosek nie powiedzie się. Błąd sieci wystąpi, gdy nie będzie można połączyć się z serwerem lub jeśli stan odpowiedzi jest inny niż 200 - zapytania, które zawierają errorsodpowiedź, mogą nadal mieć status 200. Ale na przykład nieprawidłowe zapytanie spowoduje status 400 i błąd sieci w kliencie Apollo.

Klient Apollo udostępnia cztery różne sposoby obsługi błędów mutacji:

1.) Wywołanie mutatefunkcji zwróconej przez hak zwraca Obietnicę. Jeśli żądanie zakończy się powodzeniem, obietnica zostanie rozstrzygnięta na obiekt odpowiedzi zawierający datazwrócony przez serwer. Jeśli żądanie nie powiedzie się, obietnica zostanie odrzucona z błędem. Dlatego w konsoli pojawia się komunikat „Nieobsługiwane odrzucenie” - musisz obsłużyć odrzuconą obietnicę.

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

lub ze składnią async / await:

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

Domyślnie Obietnica odrzuci on zarówno błędy GraphQL lub błędy sieciowe. Po ustawieniu parametru errorPolicy na ignorelub all, ale, obietnica będzie odrzucana tylko w przypadku błędów sieciowych. W takim przypadku błędy GraphQL będą nadal dostępne za pośrednictwem obiektu odpowiedzi, ale obietnica zostanie rozwiązana.

2.) Jedyny wyjątek od powyższego występuje, gdy udostępniasz onErrorfunkcję. W takim przypadku obietnica zawsze zostanie rozwiązana zamiast odrzucenia, ale jeśli wystąpi błąd, onErrorzostanie wywołana z błędem wynikowym. errorPolicyUstawienie dotyczy tutaj też - onErrorzawsze będzie wzywał do błędów w sieci, ale zostanie wywołana tylko z błędami GraphQL przy użyciu domyślnego errorPolicyz none. Użycie onErrorjest równoważne złapaniu odrzuconej obietnicy - po prostu przenosi moduł obsługi błędów z miejsca wywołania mutatefunkcji do miejsca wywołania haka.

3.) Oprócz mutatefunkcji useMutationhak zwraca również obiekt wynikowy. Ten obiekt ujawnia również wszelkie błędy napotkane podczas uruchamiania mutacji. W przeciwieństwie do funkcji obsługi błędów, które napisaliśmy powyżej, ten errorobiekt reprezentuje stan aplikacji . Zarówno eksponowane w ten sposób, jak errori dataobiekty istnieją dla wygody. Są odpowiednikiem aby w ten sposób:

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

Wystąpienie takiego stanu błędu może być przydatne, gdy chcesz, aby interfejs użytkownika odzwierciedlał błąd. Na przykład możesz zmienić kolor elementu, dopóki mutacja nie uruchomi się bez błędu. Zamiast samodzielnie pisać powyższy szablon, możesz po prostu użyć dostarczonego obiektu wynikowego.

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

UWAGA: Chociaż do ujawnienia interfejsu użytkownika można użyć stanu ujawnionego błędu, nie zastępuje to faktycznej obsługi błędu. Państwo musi też zapewnić onErrortelefonicznego lub catchbłąd w celu uniknięcia ostrzeżenia o nieobsłużonego odrzucenia obietnicy.

4.) Na koniec możesz także użyć apollo-link-error, aby dodać globalną obsługę błędów dla swoich żądań. Pozwala to na przykład wyświetlić okno dialogowe błędu, niezależnie od tego, w której aplikacji pochodzi żądanie.

Która z tych metod, których używasz w swojej aplikacji, zależy w dużej mierze od tego, co próbujesz zrobić (globalny vs lokalny, stan kontra wywołanie zwrotne itp.). Większość aplikacji korzysta z więcej niż jednej metody obsługi błędów.

Daniel Rearden
źródło
Dziękuję za wyjaśnienie ! Pozytywne!
Hyphæne Ohmen