Halo, Fellow Coder! 👋
Jadi kamu sudah menguasai useState dan useEffect. Sekarang kamu ingin membuat aplikasi sungguhan. Dan aplikasi sungguhan butuh data nyata.
Biasanya, data ini ada di server antah berantah, dan kita perlu mengambilnya.
”Gampang!” katamu. “Pakai fetch aja!”
Ya, betul. Tapi kalau kamu cuma asal tempel fetch di dalam komponen, kamu sedang mengundang masalah.
Gimana kalau internet lemot? Gimana kalau server meledak? Gimana kalau user pindah halaman sebelum datanya sampai?
Hari ini, kita akan belajar cara mengambil data (fetch) secara profesional. Bukan cuma asal dapat data, tapi juga menjaga User Experience (Loading & Errors).
Yuk, gas! 🚀
1. Pendekatan Naif (Jangan lakukan di production)
Ini cara kebanyakan pemula memulai:
import { useState, useEffect } from "react";
const UserProfile = () => {
const [user, setUser] = useState(null);
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users/1")
.then((res) => res.json())
.then((data) => setUser(data));
}, []);
if (!user) return <div>...</div>;
return <h1>{user.name}</h1>;
};
Ini jalan… di WiFi lokal kamu yang ngebut. Tapi apa masalahnya?
- Tidak ada Error Handling: Kalau API gagal, aplikasi crash atau layar putih kosong.
- Loading State Lemah: Cuma me-return
<div>...</div>mengimplikasikanuseritu null, padahal mungkin kita cuma lagi nunggu.
2. Pendekatan Robust: 3 State
Untuk membuat komponen yang tahan banting, kita perlu melacak tiga hal:
- Data: Hasilnya (kalau sukses).
- Loading: Apakah request masih berjalan?
- Error: Apakah ada yang salah?
Mari kita tulis ulang.
import { useState, useEffect } from "react";
const UserProfile = () => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true); // Mulai loading!
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
if (!response.ok) {
throw new Error("Network response was not ok");
}
const result = await response.json();
setData(result);
setError(null);
} catch (err) {
setError(err.message);
setData(null);
} finally {
setLoading(false); // Sukses atau gagal, stop loading
}
};
fetchData();
}, []);
if (loading) return <div>Loading... ⏳</div>;
if (error) return <div>Error: {error} ⚠️</div>;
return (
<div className="card">
<h1>{data.name}</h1>
<p>{data.email}</p>
</div>
);
};
Lihat bedanya? Sekarang user tahu persis apa yang terjadi.
- Loading? Mereka lihat spinner (atau teks).
- Error? Mereka lihat pesan error, bukan layar kosong.
- Sukses? Mereka lihat kontennya.
Inilah yang membedakan Junior dan Senior. Menangani “Unhappy Paths” (Kondisi tidak ideal).
3. Level Up: Custom Hook useFetch
Oke, kode di atas bagus. Tapi bayangkan meng-copy 3 state itu (data, loading, error) ke setiap komponen yang butuh data.
Ribet. Dan repetitif.
Ingat aturan kita? DRY (Don’t Repeat Yourself).
Mari kita ekstrak logika ini menjadi Custom Hook bernama useFetch.
// hooks/useFetch.js
import { useState, useEffect } from "react";
export const useFetch = (url) => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
try {
const res = await fetch(url);
if (!res.ok) throw new Error(res.statusText);
const json = await res.json();
setData(json);
setError(null);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
fetchData();
}, [url]); // Jalan ulang kalau URL berubah
return { data, loading, error };
};
Sekarang lihat betapa bersihnya komponen kita:
import { useFetch } from "./hooks/useFetch";
const UserProfile = () => {
const { data, loading, error } = useFetch(
"https://jsonplaceholder.typicode.com/users/1"
);
if (loading) return <div>Loading... ⏳</div>;
if (error) return <div>Error: {error} ⚠️</div>;
return (
<div>
<h1>{data.name}</h1>
<p>{data.email}</p>
</div>
);
};
Boom! 💥
Satu baris kode untuk menangani fetching, loading, dan error state.
Kamu bisa pakai useFetch hook ini di 100 komponen berbeda.
Penutup
Mengambil data itu kelihatannya simpel, tapi menangani user experience di sekitarnya itu seni.
- Selalu tangani Loading state. Jangan biarkan user menebak-nebak.
- Selalu tangkap Error. API bisa gagal. Bersiaplah.
- Ekstrak logika. Kalau kamu nulis kode yang sama dua kali, jadikan Hook.
Lain kali butuh data, jangan cuma fetch. useFetch.
Happy Coding! 💻☕