Episode ini membangun kebiasaan debugging: logging lifecycle query lewat QueryCache, memantau render cost, debugging TanStack Query dan Router dengan DevTools, serta instrumentation untuk menjaga aplikasi tetap sehat.

Setiap aplikasi akan bermasalah suatu saat: query yang tidak pernah refetch, komponen yang re-render tanpa alasan, atau navigasi yang lambat. Best practices dan observability menentukan seberapa cepat kalian menemukan akar masalahnya.
Episode 14 membahas logging query lifecycle, monitoring render cost, debugging dengan DevTools Query dan Router, serta instrumentation yang menjaga aplikasi tetap terukur.
Rutinitas observasi ini akan menghemat waktu berjam-jam. Setiap query yang aneh atau render yang boros bisa langsung diidentifikasi, bukan ditebak-tebak.
QueryCache menerima callback untuk seluruh siklus hidup query — satu tempat untuk logging tanpa menyentuh tiap useQuery:
import { QueryCache, QueryClient } from "@tanstack/react-query"
const queryCache = new QueryCache({
onError: (error, query) => {
console.error("Query gagal:", query.queryKey, error.message)
},
onSuccess: (data, query) => {
console.info("Query sukses:", query.queryKey)
},
onSettled: (data, error, query) => {
console.debug("Query selesai:", query.queryKey)
},
})
const queryClient = new QueryClient({ queryCache })onError, onSuccess, dan onSettled dipanggil untuk setiap query di aplikasi. Di development, log ini menunjukkan pola aneh — misalnya query yang gagal terus karena queryKey salah. Di production, callback yang sama bisa diteruskan ke service error reporting.
Render ulang yang berlebihan adalah musuh performa. Beberapa indikator yang patut dicurigai:
useQuery dengan queryFn yang membuat fungsi baru setiap render.options yang tidak di-memoize.React DevTools Profiler menunjukkan durasi render tiap komponen. Kombinasi dengan best practice Query — queryKey dan queryFn yang stabil — biasanya cukup meredam render boros:
const queryKey = ["pengguna", filter] as const
const { data } = useQuery({
queryKey,
queryFn: ambilPengguna,
})queryKey di-declare di luar atau di-memoize, dan queryFn merujuk fungsi stabil. TanStack Query membandingkan queryKey secara dalam; objek baru yang identik bisa memicu perilaku aneh. Fungsi stabil juga menjaga observer tidak dibuat ulang.
DevTools Query menampilkan semua query beserta status, data cache, dan aksi manual:
const isDev = import.meta.env.DEV
<QueryClientProvider client={queryClient}>
<App />
{isDev && <ReactQueryDevtools initialIsOpen={false} />}
</QueryClientProvider>import.meta.env.DEV bernilai true hanya saat development. Menjaga DevTools keluar dari bundle produksi mengurangi ukuran file dan risiko bocornya detail data internal.
Router juga punya devtools untuk inspeksi route, loader, dan pencarian:
import { TanStackRouterDevtools } from "@tanstack/router-devtools"
<RouterProvider router={router} />
{isDev && <TanStackRouterDevtools router={router} position="bottom-right" />}<TanStackRouterDevtools /> menampilkan struktur route, data loader, dan memungkinkan simulasi navigasi. Dari panel ini, kalian bisa melihat loader mana yang belum selesai dan kenapa.
DevTools membantu saat development; di production, gantikan dengan instrumentation ringan. Kirim error query ke layanan pelacak dan ukur latensi:
const queryCache = new QueryCache({
onError: (error, query) => {
reportError(error, { context: { queryKey: query.queryKey } })
},
})reportError(error, { context }) meneruskan error query beserta konteks queryKey ke layanan seperti Sentry. Di episode 21, instrumentation ini diperluas menjadi observability penuh dengan metrik cache dan performa.
Tip
Biasakan menyimpan queryKey sebagai konstanta di satu file, misalnya lib/query-keys.ts. Selain konsisten, ini memudahkan debugging karena nama key terpusat dan bisa dicari.
Episode 14 menutup observability: logging lifecycle lewat callback QueryCache, monitoring render cost dengan Profiler dan queryKey stabil, debugging dengan DevTools Query dan Router, serta instrumentation yang menyalurkan error ke layanan tracking.
Inti yang harus dibawa pulang:
Di episode 15 selanjutnya kita akan membahas full application patterns — membangun dashboard dengan TanStack Table dan Charts, mengoordinasikan query state, table state, dan router state, complex UI flows dengan nested routing, serta data-driven UI dan composition. Semua library TanStack akhirnya bekerja sama!