Salah satu cara memberikan user experience atau UX yang baik kepada user yang mengunjungi aplikasi atau website kita adalah dengan selalu memberikan error handling yang baik.

Error handling sering kali dilupakan oleh developer ketika mendevelop aplikasinya. Sehingga ketika terjadi error di production, user hanya akan mendapati sebuah blank page. Jelas ini adalah bad user experience. Ini adalah tugas dari designer dan developer untuk selalu memberikan interface yang sesuai dengan state aplikasi kita. Umumnya cukup dengan memberikan tiga state interface, yaitu saat loading, saat ada data yang di return, dan saat terjadi error. Dengan demikian kita akan lebih confident ketika aplikasi kita sudah jalan di production. Tentu kita tidak mau kan membuat user bengong mantengin layar berwarna putih a.k.a blank.

Error Handling

Dalam artikel ini akan dibahas dua jenis error dan cara meng-handle-nya, yaitu:

  1. Error pada fungsi asynchronous, bisa diatasi dengan menggunakan catch.
  2. Error pada lifecycle, atau saat me-render komponen, bisa diatas dengan Error Boundary.

Network Error

Kita sudah biasa mengatasi error pada fungsi async dengan try catch, contohnya seperti ini:

Dalam contoh di atas, saya juga me-render UI sesuai dengan state saat melakukan request data, yaitu ada idle, loading, error, dan success state. Dalam artikel ini ada penjelasan bagus dari Kent C. Dodds mengapa kita jangan menggunakan boolean untuk menggambarkan suatu state, seperti:

const [isLoading, setIsloading] = useState(false)

Sebagai contoh saya menggunakan public api dari jsonplaceholder. Saat loading maka UI yang akan ditampilkan adalah sebagai berikut:

Sedangkan jika terjadi error saat request, maka error akan di-catch dan mengupdate state menjadi β€œerror”. Sehingga UI yang akan di render adalah seperti ini,

Kita bisa coba merekayasa error dengan mengubah sedikit di url-nya, seperti menjadi

htps://jsonplaceholder.typicode.com/users/1

Error Boundary

Lalu bagaimana untuk mengatasi runtime error atau error yang terjadi dalam lifecycle component atau saat rendering di React? Contohnya kita buat dua komponen untuk merender data user yang tadi di fetch seperti ini,

Lalu kita tambahkan komponen ini di dalam <App />

Dari sini ada yang bisa menebak dimanakah errornya akan muncul? πŸ€”

Jika kita run aplikasi ini, maka kita akan seketika mendapatkan error seperti ini,

Error di atas disebabkan karena saya mencoba memanggil variabel dari sebuah object yang undefined. Jika error ini terjadi di production, maka user hanya akan mendapatkan blank page, alias hanya halaman putih kosong. User yang awam tentu akan kebingungan kalau website yang dikunjunginya hanya kosong dan hampa seperti itu.

Untuk ini error semacam ini, react telah menyediakan dua lifecycle yaitu static getDerivedStateFromError() dan componentDidCatch(). Lifecycle ini akan meng-catch error di dalam component tree, me-log error tersebut, dan memberikan fallback UI. Komponen yang kita buat menggunakan dua atau salah satu lifecycle tadi disebut sebagai Error Boundaries.

Error Boundaries ini hanya bisa dibuat dengan class component . Ketika terjadi error static getDerivedStateFromError() akan menangkap error tersebut, dan kita bisa menggunakan lifecycle ini untuk meng-update state kemudian me-render fallback UI. Sedangkan componentDidCatch() akan menangkap error beserta errorInfo yang berisi componentStack, disini kita bisa mengirim informasi error yang lebih lengkap ke service atau logger yang kita punya.

Seperti ini contohnya,

Lalu kita gunakan ErrorBoundary ini sebagai wrapper, yang akan menangkap error yang terjadi di komponen-komponen yang ada di bawahnya. Misal jika kita taruh komponen ErrorBoundary seperti ini,

Ketika terjadi error di salah satu komponen maka komponen lain juga ikut tidak ter-render dan justru fallback UI yang akan di render. Maka hasilnya seperti ini.

Loh kok sama aja? 🀬

Eits, jangan kaget dan jangan khawatir, karena di production error message di atas tidak akan tampil, kecuali kita yang sengaja menampilkannya di fallback UI yang kita buat. Kalau di development mode memang seperti itu, agar kita bisa mudah mengetahui pesan error-nya. Mudah saja, tinggal tekan tombol close di pojok kanan atas, maka kita bisa melihat ini πŸ‘‡πŸ».

Tunggu dulu, belum selesai. Dalam kasus di atas kan error-nya hanya terdapat di komponen UserProfile, mungkin kita tidak mau semua aplikasi kita digantikan oleh fallback UI, padahal yang error hanya di satu bagian saja. Error Boundary ini akan di render sesuai dengan dimana dia diletakkan. Sehingga jika kita coba membungkus komponen tadi dengan begini,

Maka fallback UI hanya akan di-render menggantikan komponen yang error saja. Hasilnya akan seperti ini,

Ini hanya sebuah contoh yang disimplifikasi, pada realitanya kita harus membuat pesan error yang lebih baik dan menambahkan logger atau error report ke sistem kita.

Lalu, jika kita menghapus code yang menyebabkan error, yaitu

Maka asalnya akan tampil seperti ini,

Anda bisa mencoba langsung disini,


Sebagaimana yang ada di dokumentasi React, Error Boundary ini tidak akan menangkap error di:

  • event handlers,
  • fungsi async,
  • server side rendering, dan
  • error yang terjadi di dalam komponen ErrorBoundary itu sendiri. Yakali, kan πŸ˜“

Ending

Dengan begini kita sudah bisa sedikit lebih confident. Saat di production terjadi error setidaknya user tidak dibiarkan menatap layar putih begitu saja, instead kita sediakan UI yang bisa memberikan pesan agar user tidak bengong dan garuk-garuk kepala.