Belajar Redux - RTK Query: Setup & useQuery
Episode 8 of 23

Belajar Redux - RTK Query: Setup & useQuery

Episode ini memperkenalkan RTK Query: membuat API client dengan createApi dan fetchBaseQuery, mendefinisikan endpoints.query, memakai hook useGetPostsQuery di komponen, serta memahami caching otomatis, deduplication request, dan status query yang lengkap.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Sampai di episode 7 kita menangani data dari API secara manual: menulis createAsyncThunk, mengelola state loading, dan memanggil dispatch di komponen. Episode 8 memperkenalkan solusi yang lebih tinggi levelnya — RTK Query. RTK Query adalah tooling data fetching dan caching yang sudah terintegrasi penuh dengan Redux Toolkit, dirancang untuk menghapus boilerplate jaringan.

Mengapa RTK Query penting? Karena kebutuhan utama aplikasi nyata bukan hanya state lokal, melainkan server state — data yang harus di-fetch, di-cache, di-update, dan disinkronkan. RTK Query mengelola siklus hidup request otomatis: hasilnya disimpan dalam cache, request yang sama tidak dikirim dua kali, dan komponen tidak perlu memikirkan status fetching secara manual.

Setup createApi dan fetchBaseQuery

Menentukan API Slice

Pusat dari RTK Query adalah createApi. Di dalamnya kita mendefinisikan reducerPath, baseQuery untuk menangani HTTP, dan endpoints yang berisi seluruh operasi data. fetchBaseQuery adalah wrapper fetch bawaan yang sudah menangani URL, headers, dan serialisasi error:

JSsrc/services/postsApi.ts
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"
 
export const postsApi = createApi({
  reducerPath: "postsApi",
  baseQuery: fetchBaseQuery({ baseUrl: "/api" }),
  endpoints: () => ({}),
})

reducerPath menentukan nama kunci state di store. baseUrl: "/api" berarti request akan menuju /api/posts ketika kita memanggil endpoint di bawahnya. Fungsi endpoints diisi lewat builder yang disediakan RTK Query.

Memasukkan API ke dalam Store

Agar hook query bekerja, hasil createApi harus didaftarkan ke store. Ada tiga hal yang perlu dipasang: reducer, middleware, dan postsApi.middleware:

JSsrc/app/store.ts
import { configureStore } from "@reduxjs/toolkit"
import { setupListeners } from "@reduxjs/toolkit/query"
import { postsApi } from "../services/postsApi"
import counterReducer from "../features/counter/counterSlice"
 
export const store = configureStore({
  reducer: {
    counter: counterReducer,
    [postsApi.reducerPath]: postsApi.reducer,
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().concat(postsApi.middleware),
})
 
setupListeners(store.dispatch)

Middleware RTK Query menangani caching, invalidation, dan re-fetch otomatis. Fungsi setupListeners mengaktifkan fitur refetchOnFocus dan refetchOnReconnect yang berguna di aplikasi nyata.

Mendefinisikan Endpoint Query

Builder Query untuk Membaca Data

endpoints.query menandai operasi pembacaan data. Builder menerima builder.query yang mengembalikan data dari server:

JSMenambahkan query posts
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"
 
export interface Post {
  id: number
  title: string
  body: string
}
 
export const postsApi = createApi({
  reducerPath: "postsApi",
  baseQuery: fetchBaseQuery({ baseUrl: "/api" }),
  endpoints: (builder) => ({
    getPosts: builder.query<Post[], void>({
      query: () => "posts",
    }),
    getPostById: builder.query<Post, number>({
      query: (id) => `posts/${id}`,
    }),
  }),
})

getPosts akan memanggil GET /api/posts, sementara getPostById memanggil /api/posts/{id}. Generic builder.query<Post[], void> berarti hasil berupa array Post dan argumen query-nya kosong. Argumen dipakai sebagai pengidentifikasi cache: nilai yang berbeda akan disimpan dalam slot cache yang berbeda.

Hook Auto-generated

Untuk setiap endpoint query, RTK Query membuat hook dengan nama terprediksi:

JSHook dari endpoint getPosts
export const { useGetPostsQuery, useGetPostByIdQuery } = postsApi

Pola namanya adalah use + kapitalisasi endpoint + Query. Hook inilah yang kita pakai di komponen tanpa perlu menulis dispatch atau useEffect sama sekali.

Memakai useGetPostsQuery di Komponen

Menarik Data dan Status

Hook query mengembalikan banyak nilai status sekaligus: data, isLoading, isError, isSuccess, error, dan refetch:

JSKomponen daftar posts
import { useGetPostsQuery } from "../services/postsApi"
 
export function PostList() {
  const { data: posts, isLoading, isError, error, refetch } = useGetPostsQuery()
 
  if (isLoading) return <p>Memuat data...</p>
  if (isError) return <p>Terjadi kesalahan: {JSON.stringify(error)}</p>
  if (isSuccess && posts) {
    return (
      <ul>
        {posts.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    )
  }
  return <button onClick={refetch}>Muat ulang</button>
}

Perhatikan alurnya: selama pertama kali dimuat isLoading bernilai true, kemudian menjadi isSuccess dengan data siap dipakai. refetch memaksa pengambilan ulang tanpa menghapus cache yang sudah ada.

Passing Argumen dan Polling

Query dengan argumen tinggal diteruskan sebagai parameter hook. RTK Query juga mendukung polling real-time lewat opsi pollingInterval:

JSQuery berargumen dengan polling
export function PostDetail({ id }: { id: number }) {
  const { data: post } = useGetPostByIdQuery(id, {
    pollingInterval: 30000,
  })
  return <article>{post ? post.body : "Memuat..."}</article>
}

Kode di atas akan menarik detail post setiap 30 detik. Nilai id yang berubah secara otomatis memicu request baru karena menjadi kunci cache yang berbeda.

Caching, Deduplication, dan Re-fetch

Cache Sekali Pakai Banyak Komponen

RTK Query menyimpan hasil di dalam store dengan struktur keyed by argumen. Dua komponen berbeda yang memakai useGetPostsQuery() berbagi satu entri cache — server hanya menerima satu request. Inilah deduplication request yang dijanjikan di awal.

Verifikasi versi paket terpasang
npm ls @reduxjs/toolkit react-redux

Kapan Data Di-fetch Ulang

Cache tidak hidup selamanya. Data dianggap segar selama batas waktu default 60 detik setelah dimuat. RTK Query menggabungkan beberapa mekanisme re-fetch:

  • refetchOnMountOrArgChange: mengambil ulang saat komponen mount dengan data basi.
  • refetchOnFocus: mengembalikan data saat tab kembali fokus.
  • refetchOnReconnect: menyegarkan saat koneksi internet pulih.
  • keepUnusedDataFor: durasi cache dipertahankan setelah tidak ada subscriber.

Ketiganya bisa diatur global di createApi atau per-endpoint, misalnya refetchOnFocus: true bila aplikasi membutuhkan data yang selalu terkini.

Tip

Periksa tab Network di Redux DevTools: kalian akan melihat request /api/posts hanya terkirim sekali meskipun beberapa komponen memakai data yang sama. Itulah bukti deduplication bekerja.

Penutup

Episode 8 menunjukkan bahwa RTK Query menghapus pekerjaan manual data fetching: createApi dan fetchBaseQuery menangani request, hook query menyediakan status lengkap, dan sistem cache mengelola siklus hidup data secara otomatis. Komponen tidak lagi memikirkan kapan harus memanggil dispatch, cukup memakai hook dan merender sesuai status.

Inti yang harus dibawa pulang:

  • createApi dengan fetchBaseQuery adalah fondasi seluruh RTK Query.
  • Daftarkan reducer dan middleware API ke store, lalu panggil setupListeners.
  • Endpoint dibedakan menjadi query untuk membaca dan mutation untuk menulis.
  • Hook useGetXQuery mengembalikan data, isLoading, isError, isSuccess, dan refetch.
  • Request yang sama otomatis di-deduplicate dan di-cache berdasarkan argumen.
  • refetchOnFocus, refetchOnReconnect, dan polling mengatur kapan data di-fetch ulang.

Di episode 9 berikutnya kita belajar mutations & cache invalidation — cara mengirim data ke server memakai useXMutation, menerapkan optimistic update lewat onQueryStarted, serta menyinkronkan daftar data dengan providesTags dan invalidatesTags setelah operasi menulis.

Belajar Redux - RTK Query: Setup & useQuery | Belajar Redux