🎯 Best Practice Menggunakan @tanstack/react-query

I am an enthusiastic researcher and developer with a passion for using technology to innovate in business and education.
Meningkatkan Kualitas Data Fetching di Aplikasi Modern
Di ekosistem React modern, mengelola data server—fetching, caching, synchronizing, dan state management—sering menjadi tantangan. Banyak developer masih memakai pendekatan manual seperti useEffect + fetch, yang rawan menyebabkan:
Request ganda yang tidak perlu
Loading state yang berantakan
Race condition
Cache yang tidak sinkron ketika data berubah
Kompleksitas logic untuk polling, retry, dan refetch
React Query hadir sebagai solusi battle-tested untuk membuat data fetching menjadi declarative, predictable, dan scalable.
Artikel ini membahas praktik terbaik (best practice) agar penggunaan React Query di proyek Anda rapi, efisien, dan maintainable.
🧠 1. Pahami Filosofi React Query: “Server State ≠ Client State”
React Query fokus pada server state, bukan data UI.
Server state berubah di luar kontrol aplikasi (misal: ada user lain update data).
Server state tidak boleh kamu rawat manual dengan useState/useEffect.
React Query memberi:
Caching otomatis
Stale-while-revalidate
Background refresh
Retry otomatis
Refetch otomatis saat window fokus
Garbage collection data lama
Optimistic update
Filosofi dasarnya:
Jangan bawa urusan server ke state management manual. Delegasikan ke React Query.
🔑 2. Gunakan queryKey Berbentuk Array (Best Practice Mutlak)
Kenapa harus array?
✔ Struktur terprediksi
✔ Mendukung nested keys
✔ Mudah di-compute
✔ Stabil untuk caching
✔ Membedakan query berdasarkan parameter
Contoh:
useQuery({
queryKey: ['users'],
queryFn: getUsers
})
useQuery({
queryKey: ['users', userId],
queryFn: () => getUserById(userId)
})
Array membuat React Query dapat:
Memahami konteks query
Meng-cache data berdasarkan struktur key
Melakukan invalidasi granular
🔁 3. Untuk POST/PUT/DELETE: Gunakan useMutation (Bukan useQuery)
Best practice yang sangat penting:
| Jenis Operasi | Hook yang dipakai | Alasan |
| GET (fetch) | useQuery | Data bisa dicache |
| POST/PUT/DELETE (mutate) | useMutation | Tidak dicache, sifatnya side effect |
Kenapa tidak memakai useQuery untuk POST?
Karena POST tidak bersifat idempotent, dan React Query bisa:
memicu refetch otomatis
menyimpan hasil POST ke cache secara tidak wajar
menganggap POST sebagai “data state”
useMutation mendesain operasi mutate sebagai action, bukan state.
Best practice:
const mutation = useMutation({
mutationFn: updateUser,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['users'] })
}
})
🔄 4. Saat Data di Update dari Server (Tanpa Invalidasi Query)
Kadang data berubah di server, tapi Anda tidak bisa memanggil invalidateQueries. Misal:
Data berubah karena user lain
Data berubah oleh sistem background
Data dikirim via WebSocket
Server melakukan push update (SSE)
Best practice React Query:
Gunakan salah satu strategi:
✔ 1. refetchInterval
Polling otomatis:
useQuery({
queryKey: ['notifications'],
queryFn: getNotifications,
refetchInterval: 5000 // setiap 5 detik
})
❓ Jika halaman tidak terbuka apakah refetch tetap berjalan?
Tidak. React Query pause saat tab tidak aktif menggunakandocument.visibilityState.
✔ 2. Gunakan WebSocket + queryClient.setQueryData
Saat server push data:
socket.on('new_message', message => {
queryClient.setQueryData(['messages'], old => [...old, message])
})
✔ 3. Gunakan SSE (Server-Sent Events)
Integrasi mudah seperti WebSocket.
✔ 4. Manual merge data dengan setQueryData
Jika update datang dari sumber lain.
⚙️ 5. Gunakan select untuk Transformasi Data di Query
Daripada transform data di component (boros render), lakukan di query:
useQuery({
queryKey: ['products'],
queryFn: getProducts,
select: data => data.map(p => ({ ...p, price: p.price / 100 }))
})
Keuntungan:
Component tetap ringan
Transformasi terjadi sekali
Konsisten
🧹 6. Atur Stale Time & Cache Time dengan Bijak
Default React Query sangat agresif karena diasumsikan untuk data yang sering berubah.
Best practice:
✔ Untuk data jarang berubah (misal countries):
staleTime: Infinity
✔ Untuk data sedang (misal: users list)
staleTime: 1000 * 60 * 5 // 5 menit
✔ Untuk detail page:
staleTime: 1000 * 30 // 30 detik
⚡ 7. Optimistic Update yang Aman
Untuk UI yang responsif:
useMutation({
mutationFn: updateTodo,
onMutate: async newTodo => {
await queryClient.cancelQueries(['todos'])
const prev = queryClient.getQueryData(['todos'])
queryClient.setQueryData(['todos'], old =>
old.map(t => t.id === newTodo.id ? newTodo : t)
)
return { prev }
},
onError: (_err, _newTodo, ctx) => {
queryClient.setQueryData(['todos'], ctx.prev)
},
onSettled: () => {
queryClient.invalidateQueries(['todos'])
}
})
🧱 8. Centralize Query Key — Jangan Hardcode
Buat file:
/src/lib/react-query-key.ts
export const queryKeys = {
users: () => ['users'] as const,
user: (id: string) => ['users', id] as const,
products: () => ['products'] as const,
}
Ini mencegah typo dan membuat invalidasi lebih aman.
🧭 9. Hindari Overfetching (Kesalahan Umum)
Jangan gunakan refetchInterval untuk semua data.
Pertanyaan utama:
Apakah data sering berubah?
Apakah perubahan harus tampil real-time?
Apakah polling terlalu mahal?
Jika tidak perlu → hilangkan polling.
🧰 10. Set Up Global di Query Client (Best Practice Paling Penting)
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: 2,
refetchOnWindowFocus: true,
refetchOnReconnect: true,
staleTime: 1000 * 60, // 1 menit
}
}
})
Global config ini memastikan aplikasi tetap efisien tanpa pengaturan manual di setiap query.
🏆 Penutup: React Query Membuat Aplikasi Lebih Stabil, Cepat, dan Bersih
Menggunakan React Query dengan best practice:
menghilangkan boilerplate
mencegah bug server state
membuat aplikasi scalable
cache bekerja otomatis
UI terasa lebih cepat dan mulus
logic lebih bersih dan terstruktur
memudahkan debugging & performance tracing
React Query bukan sekadar “data fetching library”.
Ia adalah server state ecosystem yang menyelesaikan masalah mendasar yang tidak bisa diselesaikan oleh React state biasa.
Jika digunakan dengan benar—dengan queryKey yang konsisten, strategi pada mutation, invalidasi yang tepat, dan manajemen stale time—React Query menjadi tulang punggung arsitektur front-end modern.





