Menangani kesalahan dengan react-apollo useMutation hook

10

Saya telah mencoba untuk mengatasi masalah ini tetapi belum menemukan jawaban yang kuat untuk itu. Saya mencoba menjalankan mutasi login menggunakan hook useMutation.

TLDR; Saya ingin tahu apa sebenarnya perbedaan antara opsi onError yang diteruskan dan kesalahan yang diberikan kepada saya oleh useMutation

Ini cuplikan kode saya

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

Di sisi server, saya memiliki email preset / hardcoded yang digunakan untuk login dan saya tidak menggunakan Apollo atau klien lain. Di penyelesai Mutasi Login ini, saya hanya membuang kesalahan jika menggunakan email tidak sama

throw new Error('Invalid Email');

Sekarang saya ingin menangani kesalahan ini di sisi klien (Bereaksi). Tapi kekhawatiran saya adalah bahwa jika saya menggunakan 'kesalahan' yang dikembalikan dari useMutation hook dan mencoba untuk menunjukkan kesalahan dengan cara ini

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

kesalahan diperbarui di UI tetapi kemudian segera Bereaksi menunjukkan kepada saya layar dengan Penolakan Tidak Tertangani (Kesalahan): Graphql error: My-custom-error-message

Tapi, jika saya menggunakan opsi onError yang disahkan untuk menggunakan fungsiMutate, maka itu tidak menunjukkan layar ini kepada saya dan saya bisa melakukan apa pun yang saya inginkan dengan kesalahan.

Saya ingin tahu apa sebenarnya perbedaan antara opsi onError yang diteruskan dan kesalahan yang diberikan kepada saya oleh useMutation dan mengapa React menunjukkan kepada saya layar kesalahan saat onError tidak digunakan.

Terima kasih!

d_bhatnagar
sumber

Jawaban:

33

Apollo memaparkan dua jenis kesalahan melalui API-nya: kesalahan GraphQL , yang dikembalikan sebagai bagian dari respons sebagai errors, bersama data, dan kesalahan jaringan yang terjadi ketika permintaan gagal. Kesalahan jaringan akan terjadi ketika server tidak dapat dihubungi atau jika status responsnya selain dari 200 - kueri yang ada errorsdalam respons masih dapat memiliki status 200. Tetapi kueri yang tidak valid, misalnya, akan menghasilkan status 400 dan kesalahan jaringan di Apollo Client.

Apollo Client sebenarnya menyediakan empat cara berbeda untuk menangani kesalahan mutasi:

1.) Memanggil mutatefungsi yang dikembalikan oleh hook mengembalikan Janji. Jika permintaan berhasil, Janji akan menyelesaikan ke objek respons yang mencakup datadikembalikan oleh server. Jika permintaan gagal, Janji akan menolak dengan kesalahan. Inilah sebabnya mengapa Anda melihat pesan "Penolakan Tidak Ditangani" di konsol - Anda harus menangani Janji yang ditolak.

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

atau dengan sintaks async / await:

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

Secara default, Janji akan menolak pada baik kesalahan GraphQL atau kesalahan jaringan. Dengan mengatur errorPolicy ke ignoreatau all, meskipun, Janji hanya akan menolak kesalahan jaringan. Dalam hal ini, kesalahan GraphQL masih akan dapat diakses melalui objek respons, tetapi Janji akan terselesaikan.

2.) Satu-satunya pengecualian untuk hal di atas terjadi ketika Anda menyediakan suatu onErrorfungsi. Dalam hal ini, Janji akan selalu menyelesaikan alih-alih menolak, tetapi jika terjadi kesalahan, onErrorakan dipanggil dengan kesalahan yang dihasilkan. The errorPolicyAnda mengatur berlaku di sini juga - onErrorakan selalu menyerukan kesalahan jaringan tetapi hanya akan disebut dengan kesalahan GraphQL ketika menggunakan default errorPolicydari none. Menggunakan onErrorsama dengan menangkap Janji yang ditolak - itu hanya memindahkan penangan kesalahan dari situs panggilan mutatefungsi ke situs panggilan hook.

3.) Selain mutatefungsi, useMutationhook juga mengembalikan objek hasil. Objek ini juga memperlihatkan kesalahan yang terjadi saat menjalankan mutasi. Tidak seperti fungsi penangan kesalahan yang kami tulis di atas, errorobjek ini mewakili status aplikasi . Baik objek errormaupun yang datadiekspos dengan cara ini ada sebagai kenyamanan. Mereka setara dengan melakukan ini:

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

Memiliki keadaan kesalahan seperti ini dapat berguna ketika Anda ingin UI Anda mencerminkan fakta bahwa ada kesalahan. Misalnya, Anda dapat mengubah warna elemen hingga mutasi berjalan tanpa kesalahan. Daripada harus menulis sendiri boilerplate di atas, Anda bisa menggunakan objek hasil yang disediakan.

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

CATATAN: Meskipun Anda dapat menggunakan status kesalahan yang terbuka untuk memperbarui UI Anda, melakukan hal itu bukanlah pengganti untuk benar-benar menangani kesalahan. Anda harus memberikan onErrorpanggilan balik atau catchkesalahan untuk menghindari peringatan tentang penolakan Janji yang tidak tertangani.

4.) Terakhir, Anda juga dapat menggunakan apollo-link-error untuk menambahkan penanganan kesalahan global untuk permintaan Anda. Ini memungkinkan Anda untuk, misalnya, menampilkan dialog kesalahan terlepas dari mana dalam aplikasi Anda permintaan itu berasal.

Manakah dari metode ini yang Anda gunakan dalam aplikasi Anda sangat bergantung pada apa yang Anda coba lakukan (global vs lokal, state vs callback, dll). Sebagian besar aplikasi akan menggunakan lebih dari satu metode penanganan kesalahan.

Daniel Rearden
sumber
Terima kasih untuk penjelasannya ! Terpilih!
Hyphæne Ohmen
Penjelasan luar biasa dan komprehensif. Anda telah mendapatkan suara tinggi.
David Fernandez