Episode ini mengajarkan teknik membuat aplikasi terasa instan: prefetchQuery untuk menanankan data ke cache sebelum render, serta initialData dan placeholderData untuk render instan dari data yang sudah tersedia, termasuk data dari cache query lain.

Salah satu cara paling efektif meningkatkan kualitas pengalaman pengguna bukanlah membuat fetch lebih cepat, tapi membuat fetch tidak terasa. Kalau data sudah tersedia sebelum user membutuhkannya, layar loading tidak pernah muncul. Inilah esensi prefetching dan data seeding.
Episode 10 membahas tiga alat: prefetchQuery untuk menanankan data ke cache, initialData untuk mengisi data awal, dan placeholderData untuk menampilkan data sementara. Ketiganya memakai data yang sudah ada untuk menghilangkan waktu tunggu.
prefetchQuery mengambil data dan menyimpannya ke cache tanpa menunggu komponen di-mount. Idealnya dipanggil di event handler — misalnya saat user hover sebuah link:
import { useQueryClient } from "@tanstack/react-query"
function TodoRow({ todo }) {
const queryClient = useQueryClient()
return (
<li
onMouseEnter={() =>
queryClient.prefetchQuery({
queryKey: ["todos", todo.id],
queryFn: () => fetchTodo(todo.id),
})
}
>
{todo.title}
</li>
)
}Saat mouse menyentuh baris todo, data detail todo di-prefetch ke cache. queryClient.prefetchQuery menerima konfigurasi yang sama seperti useQuery — queryKey dan queryFn — lalu menyimpan hasilnya. Ketika user akhirnya membuka halaman detail, data sudah ada.
Pola yang sama bisa dipicu sebelum navigasi halaman — misalnya di handler klik "Berikutnya" pada pagination. Data halaman berikutnya sudah hangat sebelum render, sehingga transisi terasa instan:
onClick={() => {
queryClient.prefetchQuery({
queryKey: ["todos", "page", page + 1],
queryFn: () => fetchTodos(page + 1),
})
setPage((p) => p + 1)
}}prefetchQuery menulis ke cache yang sama yang akan dibaca useQuery. Jika fetch gagal, prefetch dibuang tanpa error yang mengganggu user — prefetch bersifat best-effort.
initialData mengisi cache dengan data yang sudah kalian miliki, misalnya data yang diteruskan dari server atau state lain. Query langsung dianggap berhasil tanpa menampilkan loading:
const { data } = useQuery({
queryKey: ["todos"],
queryFn: fetchTodos,
initialData: seedTodos,
})initialData: seedTodos membuat query menampilkan seedTodos seketika, tanpa state loading. initialData dianggap data asli (bukan placeholder), sehingga isLoading tidak pernah true dan isError tidak pernah muncul — fitur yang perlu disadari karena error tersembunyi di balik data awal.
Salah satu penggunaan initialData paling cerdas: memakai data query lain yang berisi data yang sama. Contoh klasiknya, detail todo di-seed dari data list todo:
const { data } = useQuery({
queryKey: ["todos", id],
queryFn: () => fetchTodo(id),
initialData: () =>
queryClient.getQueryData(["todos"])?.find((t) => t.id === id),
})initialData menerima function yang mengembalikan data dari cache lain. queryClient.getQueryData(["todos"]) membaca daftar yang sudah ada, lalu .find mengambil item yang dibutuhkan. Hasilnya halaman detail menampilkan data instan dan menyegarkan di latar belakang.
Kedua opsi ini sering tertukar. Perbedaannya penting:
initialData → data asli: isi cache, tanpa loading, tanpa isFetching
placeholderData → data tiruan: tampil sementara, status loading tetap berjalanRingkasan initialData → data asli: isi cache menegaskan bahwa initialData benar-benar menulis ke cache. placeholderData hanya menampilkan data sementara sementara fetch berjalan di latar belakang — status isFetching tetap true sehingga indikator bisa tetap tampil.
keepPreviousData di episode 9 — dan kalian tetap ingin fetch terbaru berjalan.Karena initialData menandai query sebagai sukses, data bisa menampilkan info basi tanpa disadari. Pertimbangkan staleTime yang sesuai, atau biarkan background refetch segera berjalan. Jika kalian hanya butuh data tayangan tanpa menulis cache, placeholderData biasanya pilihan yang lebih aman.
Tip
Kombinasi terbaik: prefetch di event handler untuk menyiapkan cache lebih awal, lalu biarkan useQuery normal membaca cache yang sudah hangat. initialData sebaiknya dipakai untuk data yang memang sudah ada di tangan, bukan untuk meniru prefetch.
Episode 10 memberi kalian tiga cara menanamkan data agar aplikasi terasa instan: prefetchQuery untuk menyiapkan cache lebih dulu, initialData untuk mengisi cache dengan data valid, dan placeholderData untuk menampilkan data sementara.
Inti yang harus dibawa pulang:
prefetchQuery menulis cache tanpa menunggu render komponen.initialData mengisi cache dengan data asli tanpa state loading.placeholderData menampilkan data sementara sambil fetch berjalan.initialData.initialData menandai query sukses, jadi perhatikan kebasian datanya.Di episode 11 selanjutnya kita akan membahas optimistic updates — memperbarui UI sebelum server menjawab dengan onMutate dan setQueryData, lalu rollback otomatis di onError. Ini pola kunci untuk fitur seperti like dan toggle yang terasa instan.