Episode ini mengajarkan debugging dengan React Query Devtools untuk memantau cache, status query, dan retry, serta troubleshooting masalah umum: query tidak refetch, infinite loop, error serialization, dan memory leak di cache.

TanStack Query menangani begitu banyak hal otomatis — refetch, retry, invalidasi — sehingga ketika perilakunya tidak seperti dugaan, kalian butuh mata tambahan. Untungnya library ini punya React Query Devtools: panel yang menampilkan seluruh isi cache dan status tiap query secara real-time.
Episode 17 mengajarkan cara memakai devtools, lalu troubleshooting untuk empat masalah paling umum yang dialami developer.
Devtools sudah diinstall di episode 0. Tinggal render komponennya di aplikasi:
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
function App() {
return (
<>
<Todos />
<ReactQueryDevtools initialIsOpen={false} />
</>
)
}ReactQueryDevtools menambahkan panel debug yang bisa dibuka dari pojok layar. initialIsOpen={false} membuat panel tertutup saat awal. Devtools tidak mengubah perilaku aplikasi — dia hanya jendela pengamatan.
Panel devtools memberikan informasi yang tidak bisa dilihat dari code saja:
queryKey.queryKey: ["todos"] → status: stale, 2 observer, 1 fetch
queryKey: ["todos", 5] → status: fetching, 1 observer
queryKey: ["config"] → status: fresh, 0 observer (inactive)Baris queryKey: ["todos"] → status: stale menampilkan contoh status query. Jika sebuah query tidak di-refetch seperti harapan, panel inilah tempat pertama untuk memeriksa status dan staleTime-nya.
Gejala paling umum: query berjalan sekali dan tidak pernah di-refetch, meskipun data sudah berubah di server. Kemungkinan penyebab:
1. staleTime terlalu besar → data dianggap segar terus
2. refetchOnWindowFocus false → tidak ada trigger
3. tidak ada invalidateQueries → cache tidak pernah ditandai basiPenyebab nomor 1 — staleTime terlalu besar — paling sering terjadi. Ingat prinsip episode 7: trigger refetch hanya bekerja pada query yang stale. Periksa staleTime, atau invalidate manual di devtools untuk memastikan mekanisme bekerja.
Query yang refetch terus menerus biasanya berasal dari queryFn yang mengubah sesuatu yang ikut menjadi bagian dari queryKey:
// berbahaya: state yang diubah menyebabkan key berubah → fetch → berubah lagi
const { data } = useQuery({
queryKey: ["todos", filter],
queryFn: () => fetchTodos(filter),
})Jika filter berubah di dalam queryFn atau dipengaruhi hasilnya, key berubah, fetch baru berjalan, key berubah lagi — begitulah infinite loop. queryFn harus murni: membaca parameter dari queryKey, tidak pernah mengubahnya. Pastikan juga function object baru tidak dibuat di dalam render dengan cara yang mengubah dependency.
Jika error dari queryFn tidak bisa di-serialize — misalnya Error dengan properti non-standar saat persist cache — hydration akan gagal. Pastikan error yang dilempar berupa Error sederhana:
throw new Error("Gagal mengambil data")
throw new ApiError(status, "Pesan untuk user")throw new Error("...") membuat error yang aman untuk serialisasi. ApiError di atas adalah subclass yang field-nya string dan number — tidak ada referensi siklik atau fungsi yang akan bermasalah saat cache dipersist.
gcTime yang sangat besar plus query yang sering dibuat dengan key unik bisa menumpuk di memori. Solusinya: pastikan gcTime masuk akal, batasi query yang dibuat dinamis, dan aktifkan devtools untuk memantau jumlah entri cache. Jika cache membengkak, pertimbangkan normalisasi data dari episode 13.
Tip
Gunakan devtools sebagai bagian alur kerja, bukan alat darurat. Buka panel saat menulis query baru, periksa status dan jumlah fetch, lalu lanjutkan. Kebiasaan ini menangkap bug jauh sebelum sampai ke production.
Episode 17 melengkapi toolkit debugging kalian: React Query Devtools untuk mengamati cache dan status secara real-time, plus penanganan empat masalah klasik — query yang tidak refetch, infinite loop, error serialization, dan memory leak cache.
Inti yang harus dibawa pulang:
ReactQueryDevtools menampilkan cache, status, dan jumlah fetch.staleTime terlalu besar menyebabkan query tidak pernah refetch.queryFn yang mengubah queryKey memicu infinite loop.Error sederhana agar aman untuk serialisasi cache.Di episode 18 selanjutnya kita akan membahas testing — membuat QueryClient khusus test dengan retry: false, memakai testing-library dan renderHook, meng-mock API dengan MSW, menguji state loading, success, dan error, serta fake timers untuk refetchInterval.