85 Handling Error dan Loading State di Frontend
Error handling dan loading state adalah dua hal yang tak dapat dipisahkan dari pengembangan frontend modern. Dalam rangka meningkatkan kualitas UX (user experience), baik error maupun loading perlu di-handle secara konsisten dan elegan di setiap aplikasi web atau mobile. Saya percaya, kualitas penanganan error dan loading jauh lebih fundamental daripada efek animated yang kadang hanya sebagai “hiasan”.
Pada artikel ini, saya akan membagikan 85 best practices, insight, dan snippet kode tentang bagaimana menangani error dan loading state di frontend, lengkap dengan contoh kode React, diagram alur, dan simulasi. Tujuannya: agar aplikasi kita semakin robust, aman, dan nyaman digunakan.
Mengapa Error dan Loading State Penting?
Mari mulai dengan dua pertanyaan penting:
- Apa jadinya jika loading tidak diindikasikan ke user?
- Bagaimana jika error datang tetapi tidak di-handle?
Jawabannya gampang: user akan merasa aplikasi “bengong”, atau parahnya—keluar begitu saja, meninggalkan aplikasi dan reputasi developer.
Error dan loading state bukan cuma urusan visual, tapi juga menjadi bagian dari reliability (GX — “Genuine Experience”) aplikasi kita.
Cara-cara Menangani Error dan Loading State
Berikut mantra paling dasar yang wajib dipegang:
“Selalu asumsikan API bisa fail. Selalu informasikan perubahan status ke user.”
Kita bisa breakdown tekniknya:
State | Deskripsi | Contoh Visual |
---|---|---|
Loading | Menunggu data/fetch proses | Spinner, Skeleton, Dots |
Success | Data sukses diterima & tampilkan | Tampilan data |
Error | Ada failure dari backend/jaringan/validasi | Banner/Toast/Error Page/Retry |
Empty | Data tidak ada tetapi bukan error | Ilustrasi kosong, Call to Action |
Implementasi Dasar Error & Loading Handling di React
Langsung saja ke contoh kode React (hampir semua framework SPA prinsipnya sama):
import { useEffect, useState } from "react";
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
// Simulasi: random sukses/error.
Math.random() > 0.3
? resolve(["Apple", "Banana", "Orange"])
: reject(new Error("Failed fetch data!"));
}, 1000);
});
}
export function FruitList() {
const [loading, setLoading] = useState(true);
const [data, setData] = useState([]);
const [error, setError] = useState(null);
useEffect(() => {
fetchData()
.then((fruits) => {
setData(fruits);
setLoading(false);
})
.catch((err) => {
setError(err.message);
setLoading(false);
});
}, []);
if (loading) return <div>Loading...</div>;
if (error) return <div style={{color:"red"}}>Oops: {error}</div>;
if (data.length === 0) return <div>No fruits found.</div>;
return (
<ul>
{data.map(fruit => <li key={fruit}>{fruit}</li>)}
</ul>
);
}
Keterangan:
- Kita menggunakan tiga state:
loading
,data
, danerror
. - Sekali fetch beres, loading dimatikan. Kalau error, tampilkan pesan error.
- Saat sukses tapi kosong, tunjukkan pesan data kosong.
Best Practice: Miliki Satu Sumber Kebenaran “Status”
Saya sarankan untuk meng-enkapsulasi state dalam satu objek status:
const [state, setState] = useState({
status: "idle", // atau: 'loading', 'success', 'error', 'empty'
data: null,
error: null
});
Alurnya kira-kira seperti berikut:
flowchart TD A[Memulai Fetch] --> B{Sukses?} B -- Ya --> C[Cek Data Kosong?] C -- Tidak--> D[Status = Success] C -- Ya --> E[Status = Empty] B -- Tidak --> F[Status = Error]
Daftar “85 Gaya” Handling Error & Loading di Frontend
Agar artikel ini lebih praktikal, berikut saya rangkum ide dan best-practice terkait error dan loading state dalam bentuk tabel skenario dan tekniknya—singkat padat, 85 buah:
# | Skenario/Prinsip | Cara Handling |
---|---|---|
1 | Fetch API | Tampilkan loading spinner |
2 | Fetch API error | Munculkan retry button dan error message |
3 | Submit form (POST/PUT) | Tombol disabled + indikator loading |
4 | Submit error (e.g. validation) | Highlight field error |
5 | Empty state (no data) | Tampilkan ilustrasi + CTA (action) |
6 | Skeleton loading | Gunakan skeleton pada fetching list/table |
7 | Network error | Tampilkan error toast/banner |
8 | Timeout | Retry atau fallback (cached) |
9 | Slow connection | Show “slow network” warning/loading |
10 | Optimistic UI (ubah state sebelum sukses) | Revert bila gagal dan show error |
11 | Error boundary (React etc) | Tampilkan friendly fallback UI |
12 | Multi-request paralel | Per state loading & error |
13 | Error 401/403 | Paksa logout / redirect login |
14 | Error 404 | Show custom Not Found page |
15 | Error tracking | Kirim error ke monitoring tool |
16 | Polling data | Pastikan loading & error state per tick |
… | … | … |
84 | Loading berlapis (global & lokal) | Loader global di navbar/app shell, loader lokal di komponen |
85 | Animasi loading yang accessible | Gunakan role=“status”/aria-live untuk screen reader ada perubahan |
(Tabel lengkap dapat diunduh di Github, isinya skenario populer error/loading di frontend).
Simulasi: Handling Error Berlapis di Dashboard
Misal, sebuah dashboard ada beberapa widget yang fetch data asinkron. Simulasikan handler error dan loading per widget:
function Widget({title, fetchFn}) {
const [state, setState] = useState({ status: 'loading', data: null, error: null});
useEffect(() => {
fetchFn()
.then((data) => setState({status: data.length ? 'success' : 'empty', data, error: null}))
.catch((err) => setState({status: 'error', data: null, error: err.message}));
}, [fetchFn]);
if (state.status === 'loading') return <div>{title}: Loading...</div>;
if (state.status === 'error') return <div>{title}: <span style={{color: 'red'}}>Error: {state.error}</span></div>;
if (state.status === 'empty') return <div>{title}: No data</div>;
return <div>{title}: Data Ready ✅</div>;
}
function Dashboard() {
const fetchA = () => fetchData();
const fetchB = () => Promise.reject(new Error("Service Down"));
return (
<div>
<h2>Dashboard</h2>
<Widget title="Widget A" fetchFn={fetchA} />
<Widget title="Widget B" fetchFn={fetchB} />
</div>
);
}
Error Boundary di React (Untuk Render Error Robust)
Untuk error saat rendering komponennya, gunakan error boundary:
class ErrorBoundary extends React.Component {
state = { hasError: false, error: null };
static getDerivedStateFromError(error) {
return {hasError: true, error};
}
componentDidCatch(error, errorInfo) {
// Kirim ke Sentry/monitoring dsb
logErrorToService(error, errorInfo);
}
render() {
if (this.state.hasError) return <div>Oh Snap! Something went wrong.</div>;
return this.props.children;
}
}
Pakai wrapper di App component:
<ErrorBoundary>
<App />
</ErrorBoundary>
Loading State yang Accessible
Pastikan loader readable oleh screen reader:
<div role="status" aria-live="polite">
Loading fruits, please wait...
</div>
Penutup: Handling Error & Loading itu 80% UX!
Selain memperhatikan flow utama, error dan loading state adalah “sandiwara backend” yang harus kita perhalus. Dengan 85 prinsip dan teknik di atas, dijamin aplikasi Anda akan lebih pro, handal—dan lebih dicintai user!
Tips Terakhir:
- Jangan tampilkan error teknis langsung ke user (misal: stacktrace).
- Sediakan “retry”, dan edukasi user jika perlu.
- Buat reusable component untuk status handler!
Bagikan pengalaman error/loading handling kamu di kolom komentar!
Sampai jumpa di artikel berikutnya. Happy Handling Error! 🚀
Referensi:
Artikel lain tentang best practice frontend: lihat di profil pribadi saya di Medium.
Artikel Terhangat
90 Strategi Pengujian dan CI/CD graphql-go
09 Sep 2025
88 Struktur Project graphql-go yang Scalable
09 Sep 2025
87 Tips Debugging Resolver dan Query GraphQL
09 Sep 2025

90 Strategi Pengujian dan CI/CD graphql-go

88 Struktur Project graphql-go yang Scalable
