Episode ini menghubungkan TanStack Query ke berbagai backend: integrasi REST dan GraphQL, strategi caching dengan staleTime dan gcTime, invalidasi untuk data real-time dengan polling, serta offline support memakai persist query client.

Query function hanyalah fungsi yang mengembalikan promise — artinya TanStack Query bisa berbicara dengan backend apa pun: REST, GraphQL, WebSocket, bahkan layanan lokal. Episode 13 menghubungkan semua itu dengan strategi cache yang tepat.
Episode 13 membahas integrasi REST dan GraphQL, strategi caching dengan staleTime dan gcTime, invalidasi untuk data real-time, serta offline support dengan persist query client.
Tujuan akhirnya sederhana: data cepat, tetap segar, dan aplikasi tetap berguna meskipun koneksi terputus. Semua dicapai lewat pengaturan cache, bukan arsitektur baru.
REST tinggal memetakan endpoint ke queryKey dan queryFn. Untuk GraphQL, queryFn membungkus request POST dengan query string:
const graphQLFetcher = async ({ query, variables }) => {
const res = await fetch("/graphql", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query, variables }),
})
const json = await res.json()
if (json.errors) throw new Error(json.errors[0].message)
return json.data
}
const { data } = useQuery({
queryKey: ["proyek", filter],
queryFn: () =>
graphQLFetcher({
query: "query Proyek($filter: String) { proyek(filter: $filter) { id nama } }",
variables: { filter },
}),
})graphQLFetcher mengirim query dan variables, lalu melempar error bila GraphQL mengembalikan errors. Perhatikan queryKey berisi filter — mengganti filter berarti query baru, sehingga cache per variabel terjaga rapi.
staleTime mengatur kapan data dianggap basi, gcTime mengatur berapa lama cache bertahan tanpa pemakaian. Strategi yang umum:
const { data: profil } = useQuery({
queryKey: ["profil"],
queryFn: ambilProfil,
staleTime: 5 * 60_000,
})
const { data: hargaSaham } = useQuery({
queryKey: ["harga"],
queryFn: ambilHarga,
staleTime: 5_000,
refetchInterval: 5_000,
})Profil yang jarang berubah memakai staleTime lima menit — nyaris tanpa request ulang. Harga saham yang dinamis memakai staleTime lima detik plus refetchInterval: 5_000 agar selalu disinkronkan. Kuncinya: sesuaikan staleTime dengan seberapa cepat data berubah.
Selain polling, invalidasi bisa dipicu dari event eksternal — misalnya WebSocket memberi tahu ada data baru. Invalidasi hanya menandai query sebagai basi; refetch berjalan sesuai kebijakan masing-masing query:
socket.onmessage = (event) => {
const pesan = JSON.parse(event.data)
if (pesan.tipe === "data-baru") {
queryClient.invalidateQueries({ queryKey: ["laporan"] })
}
}invalidateQueries({ queryKey: ["laporan"] }) menandai semua query dengan awalan laporan sebagai basi. Jika halaman sedang menampilkan data itu, refetch berjalan otomatis; jika tidak, cukup ditandai sampai halaman dibuka lagi — efisien tanpa membuang request.
Persist query client menyalin cache ke storage lokal, sehingga aplikasi punya data saat offline atau setelah refresh:
import { persistQueryClient } from "@tanstack/react-query-persist-client"
import { createSyncStoragePersister } from "@tanstack/query-sync-storage-persister"
const persister = createSyncStoragePersister({
storage: window.localStorage,
})
persistQueryClient({
queryClient,
persister,
maxAge: 24 * 60 * 60 * 1000,
})createSyncStoragePersister({ storage: window.localStorage }) menyimpan cache ke localStorage. maxAge: 24 * 60 * 60 * 1000 membatasi cache yang direstore maksimal sehari. Saat offline, aplikasi menampilkan data tersimpan; saat online, query yang basi di-fetch ulang.
Warning
Hati-hati menyimpan data sensitif di localStorage lewat persister. Batasi maxAge dan filter queryKey agar data rahasia tidak ter-persist lebih lama dari yang dibutuhkan.
Episode 13 menutup integrasi API dan strategi cache: REST dan GraphQL bekerja lewat query function yang sama, staleTime dan gcTime disesuaikan dengan dinamika data, invalidasi dari event real-time menjaga kesegaran, dan persist cache membuat aplikasi tetap hidup saat offline.
Inti yang harus dibawa pulang:
Di episode 14 selanjutnya kita akan membahas best practices dan observability — logging query lifecycle, monitoring render cost, debugging TanStack Query dan Router dengan DevTools, serta instrumentation untuk produksi. Waktunya memastikan aplikasi kalian sehat!