Skip to main content
BlogWeb Dev

React Query vs SWR: Mana yang Digunakan di 2026

Perbandingan TanStack Query dan SWR untuk pengambilan data di Next.js secara berdampingan — dengan contoh kode nyata untuk mutasi, caching, dan SSR.

Matthews Wong

Software Engineer

Juni 20258 menit baca
React Query vs SWR: Mana yang Digunakan di 2026

Foto oleh Unsplash

Baik React Query (kini TanStack Query) maupun SWR memecahkan masalah yang sama: mengelola remote state di React tanpa prop drilling dan spaghetti useEffect yang dihasilkan dari panggilan fetch manual. Saya telah menggunakan keduanya di proyek produksi. SWR menggerakkan situs Next.js publik yang lebih sederhana; React Query menjalankan dashboard untuk alat ERP internal dengan mutasi kompleks, pembaruan optimis, dan dukungan offline.

DimensiSWRReact Query
Ukuran bundleSekitar 4KB minified dan gzippedSekitar 13KB minified dan gzipped
MutationsPanggilan mutate() manual, tanpa API mutation bawaanHook useMutation khusus dengan optimistic update
Model cachingCache stale-while-revalidate yang sederhanaCache yang bisa dikonfigurasi lewat query key, staleTime, dan gcTime
Dukungan offlineRevalidate-on-reconnect dasarAntrean offline dan retry mutation bawaan
DevToolsTidak ada panel devtools resmiDevtools khusus untuk memeriksa cache dan state query
Paling cocok untukData fetching sederhana di halaman publikDashboard kompleks dengan mutation dan kebutuhan offline

Perbedaan Inti: Filosofi

SWR (Stale-While-Revalidate) adalah dari Vercel dan dioptimalkan untuk ekosistem Vercel/Next.js. Filosofinya adalah surface API minimal — satu hook useSWR mencakup sebagian besar kasus penggunaan. React Query dari TanStack lebih beropini tentang manajemen server state, dilengkapi dengan DevTools, dan memiliki dukungan kelas pertama untuk mutasi, pagination, infinite query, dan mode offline.

Apa yang Mereka Bagikan

Kedua library mendeduplikasi request — jika tiga komponen di halaman yang sama memanggil useSWR('/api/user') atau useQuery(['user']), hanya satu request HTTP yang dikirim. Keduanya melakukan revalidasi saat window fokus dan reconnect. Keduanya mendukung background refetching, fungsi fetcher kustom, dan konfigurasi global.

Kapan SWR Menang

SWR menang untuk situs berat konten di mana kamu terutama perlu mengambil dan menampilkan data dengan mutasi sederhana sesekali. API-nya lebih kecil untuk dipelajari, terintegrasi sempurna dengan ekosistem Vercel, dan untuk CRUD sederhana tanpa kebutuhan invalidasi cache yang kompleks, ergonomisnya lebih bersih.

Feature Comparison: React Query vs SWR

┌─────────────────────────┬──────────────┬──────────────┐
│ Feature                 │ React Query  │     SWR      │
├─────────────────────────┼──────────────┼──────────────┤
│ Bundle size (min+gzip)  │   ~13.5 kB   │   ~4.2 kB    │
│ Mutations               │   ✅ Built-in │   ⚠️ Manual  │
│ Optimistic updates      │   ✅ Easy     │   ✅ Possible │
│ Infinite scroll         │   ✅ Built-in │   ✅ Built-in │
│ Offline support         │   ✅ Yes      │   ⚠️ Partial  │
│ DevTools                │   ✅ Official │   ❌ None     │
│ Server State (SSR)      │   ✅ Full     │   ✅ Full     │
│ Background refetch      │   ✅ Yes      │   ✅ Yes      │
│ Request deduplication   │   ✅ Yes      │   ✅ Yes      │
│ Prefetching             │   ✅ Yes      │   ⚠️ Manual  │
│ Learning curve          │   Medium     │   Low        │
│ Best for                │ Complex apps │ Simple fetch │
└─────────────────────────┴──────────────┴──────────────┘

Di Next.js App Router, prefetch data sisi server menggunakan QueryClient.prefetchQuery() di Server Component-mu, kemudian teruskan state yang di-dehydrate ke HydrationBoundary di Client Component. Ini memberimu zero-loading-state pada render pertama sambil tetap mendapatkan semua manajemen cache sisi klien React Query.

Mutasi: Di Mana React Query Unggul

Mutasi SWR memerlukan pembaruan cache manual melalui fungsi mutate() — kamu memberi tahu SWR apa nilai cache baru seharusnya. Hook useMutation React Query memiliki siklus hidup onMutate / onError / onSettled yang membuat pembaruan optimis, rollback pada error, dan invalidasi cache menjadi pola terstruktur daripada logika ad-hoc.

Infinite Query dan Pagination

Kedua library mendukung infinite scrolling dengan useInfiniteQuery (React Query) dan useSWRInfinite (SWR). Implementasi React Query lebih ergonomis — array pages dan fungsi fetchNextPage() menangani sebagian besar pola pagination tanpa logika kustom. SWR memerlukan pengkabelan manual lebih banyak tapi memberimu lebih banyak kontrol atas strategi penggabungan data.

// ─── React Query: full mutation with optimistic update ───
import { useMutation, useQueryClient } from "@tanstack/react-query"

function useUpdateProduct() {
  const queryClient = useQueryClient()

  return useMutation({
    mutationFn: (data: UpdateProductDto) =>
      fetch(`/api/products/${data.id}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(data),
      }).then((r) => r.json()),

    // Optimistic update
    onMutate: async (newProduct) => {
      await queryClient.cancelQueries({ queryKey: ["products", newProduct.id] })
      const prev = queryClient.getQueryData(["products", newProduct.id])
      queryClient.setQueryData(["products", newProduct.id], newProduct)
      return { prev }
    },

    onError: (_err, newProduct, ctx) => {
      queryClient.setQueryData(["products", newProduct.id], ctx?.prev)
    },

    onSettled: (_data, _err, vars) => {
      queryClient.invalidateQueries({ queryKey: ["products", vars.id] })
      queryClient.invalidateQueries({ queryKey: ["products"] })
    },
  })
}

// ─── SWR: fetching + manual mutation ───
import useSWR, { mutate } from "swr"

const fetcher = (url: string) => fetch(url).then((r) => r.json())

function useProducts() {
  const { data, error, isLoading } = useSWR("/api/products", fetcher, {
    revalidateOnFocus: true,
    dedupingInterval: 5000,
  })

  const updateProduct = async (id: string, payload: Partial<Product>) => {
    // Optimistic update with SWR
    await mutate(
      "/api/products",
      async (current: Product[]) => {
        const updated = await fetch(`/api/products/${id}`, {
          method: "PATCH",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(payload),
        }).then((r) => r.json())
        return current.map((p) => (p.id === id ? updated : p))
      },
      { optimisticData: (current) =>
          current?.map((p) => (p.id === id ? { ...p, ...payload } : p)) }
    )
  }

  return { data, error, isLoading, updateProduct }
}

Server State vs Client State

Wawasan kunci yang dibagikan kedua library: server state secara fundamental berbeda dari client state. Client state (toggle UI, input form, modal buka/tutup) milik useState atau state manager seperti Zustand. Server state (record database, respons API) milik React Query atau SWR. Mencampurnya menyebabkan data basi, race condition, dan bug sinkronisasi.

Menggunakan kedua library dalam codebase yang sama menggandakan biaya bundle dan menciptakan dua layer cache terpisah yang tidak saling mengetahui. Pilih satu saat awal proyek dan pertahankan. Jika kamu mewarisi codebase dengan keduanya, migrasikan semuanya ke React Query (lebih capable) dan hapus SWR.

Mengintegrasikan dengan Next.js App Router

Di Next.js App Router, Server Component menangani pengambilan awal — tidak perlu React Query atau SWR untuk first paint. React Query dan SWR masuk untuk interaksi sisi klien setelah hidrasi: merefresh data pada aksi pengguna, polling untuk pembaruan langsung, dan mutasi. Bungkus Client Component-mu dalam QueryClientProvider atau SWRConfig di root layout-mu.

Rekomendasi Saya

Untuk proyek Next.js baru: mulai dengan SWR. Ini mencakup 80% kasus penggunaan dengan bundle lebih kecil dan model mental yang lebih sederhana. Migrasi ke React Query jika kamu membutuhkan DevTools untuk men-debug cache state, melakukan mutasi optimis yang memerlukan rollback, memiliki dependent query yang kompleks, atau membutuhkan perilaku offline-first. Untuk dashboard ERP, panel admin, dan aplikasi berat data: mulai dengan React Query.

Sumber & Bacaan Lanjutan

Artikel Terkait

FAQ

Pertanyaan Umum

Jawaban singkat untuk pertanyaan yang paling sering diajukan pembaca tentang topik ini.

Apa perbedaan utama antara React Query dan SWR?

SWR dari Vercel dirancang dengan surface API minimal — satu hook useSWR mencakup sebagian besar kasus penggunaan — dan dioptimalkan untuk ekosistem Vercel/Next.js. React Query (TanStack Query) lebih beropini tentang manajemen server state, dilengkapi DevTools, serta memiliki dukungan kelas pertama untuk mutasi, pagination, infinite query, dan mode offline. Perbedaan ukuran bundle (~4 KB untuk SWR vs ~13,5 KB untuk React Query) penting di situs konten, namun tidak terlalu berpengaruh di dashboard.

Kapan sebaiknya memilih SWR daripada React Query?

SWR adalah pilihan default yang lebih baik untuk situs berat konten di mana kamu terutama perlu mengambil dan menampilkan data dengan mutasi sederhana sesekali. API-nya lebih kecil untuk dipelajari dan terintegrasi sempurna dengan ekosistem Vercel. Jika kebutuhan datamu hanya 'tampilkan daftar, tampilkan detail, mungkin lakukan pembaruan sederhana', SWR sudah cukup dan menghemat 9 KB JavaScript.

Mengapa React Query menangani mutasi lebih baik daripada SWR?

Mutasi SWR memerlukan pembaruan cache manual melalui fungsi mutate() — kamu harus secara eksplisit memberi tahu SWR apa nilai cache baru yang seharusnya. Hook useMutation React Query memiliki siklus hidup onMutate / onError / onSettled yang menjadikan pembaruan optimis, rollback saat error, dan invalidasi cache sebagai pola terstruktur, bukan logika ad-hoc. Untuk dashboard ERP di mana pengguna mengedit record dan membutuhkan umpan balik UI segera dengan rollback saat kegagalan jaringan, model mutasi React Query jauh lebih rapi.

Bagaimana React Query dan SWR berintegrasi dengan Next.js App Router?

Di Next.js App Router, Server Component menangani pengambilan data awal — React Query maupun SWR tidak dibutuhkan untuk first paint. Setelah hidrasi, keduanya menangani interaksi sisi klien seperti merefresh data saat aksi pengguna, polling pembaruan langsung, dan mutasi. Kamu bisa prefetch data di sisi server menggunakan QueryClient.prefetchQuery() dan meneruskan state yang di-dehydrate ke HydrationBoundary di Client Component untuk zero-loading-state pada render pertama; SWR memiliki prop fallback yang setara untuk pola yang sama.

Apakah boleh menggunakan React Query dan SWR sekaligus dalam satu proyek?

Tidak — menggunakan kedua library dalam codebase yang sama menggandakan biaya bundle dan menciptakan dua layer cache terpisah yang tidak saling mengetahui. Pilih satu saat awal proyek dan pertahankan. Jika kamu mewarisi codebase yang menggunakan keduanya, rekomendasinya adalah migrasikan semuanya ke React Query dan hapus SWR, karena mempertahankan keduanya 'sementara' hampir selalu menjadi permanen.