Next.js
Data Fetching

Next.js | Data Fetch

Pengambilan data adalah bagian inti dari setiap aplikasi. Halaman ini merangkum cara resmi mengambil, menyimpan cache, dan merevalidasi data di Next.js App Router (React 19).

Ada empat cara utama:

  1. Pada server, dengan fetch
  2. Pada server, dengan pustaka pihak ketiga
  3. Pada klien, memanggil Route Handler
  4. Pada klien, dengan pustaka pihak ketiga.

Mengambil Data pada Server dengan fetch

Next.js memperluas native fetch Web API (opens in a new tab) agar setiap permintaan dapat dikonfigurasi cache dan revalidasinya. React memoisasi fetch secara otomatis saat render pohon Server Component.

Kita dapat menggunakan fetch dengan async/await di Komponen Server, Pengendali Rute, dan Server Action.

Contohnya:

app/page.tsx
async function getData() {
  const res = await fetch("https://api.example.com/...");
  // Nilai kembalian *tidak* diserialkan
  // Kita dapat mengembalikan Tanggal, Peta, Set, dll.
 
  if (!res.ok) {
    // Ini akan mengaktifkan Batas Kesalahan `error.js` terdekat
    throw new Error("Gagal mengambil data");
  }
 
  return res.json();
}
 
export default async function Page() {
  const data = await getData();
 
  return <main></main>;
}

Catatan:

  • Next.js menyediakan helper seperti cookies dan headers di Server Component; penggunaannya membuat rute dinamis karena bergantung pada data per permintaan.
  • Di Route Handler, fetch tidak dimemoisasi karena handler bukan bagian pohon React.
  • Untuk async/await di Server Component dengan TypeScript, gunakan TS 5.1.3+ dan @types/react 18.2.8+.

Penyimpanan Cache Data

Penyimpanan cache menyimpan data sehingga tidak perlu diambil ulang dari sumber data pada setiap permintaan.

Secara default, Next.js menyimpan nilai yang dikembalikan fetch dalam Data Cache pada server. Data dapat diambil saat build atau saat request, disimpan, dan digunakan kembali.

// 'force-cache' adalah default, dan dapat dihilangkan
fetch("https://...", { cache: "force-cache" });

Permintaan fetch yang menggunakan metode POST juga secara otomatis disimpan dalam cache. Kecuali jika berada dalam Pengendali Rute yang menggunakan metode POST, maka permintaan tersebut tidak akan disimpan dalam cache.

Apa itu Penyimpanan Data?

Penyimpanan Data adalah cache HTTP yang persisten. Tergantung pada platform kita, cache dapat secara otomatis diperluas dan dibagikan di beberapa wilayah.

Revalidasi Data

Revalidasi membersihkan Data Cache dan mengambil data terbaru.

Data yang sudah disimpan dalam cache dapat divalidasi kembali dengan dua cara:

  • Revalidasi berbasis waktu: otomatis setelah jeda tertentu.
  • Revalidasi berdasarkan permintaan: manual lewat tag atau path ketika ada peristiwa (mis. CMS update atau Server Action).

Revalidasi Berbasis Waktu

Gunakan opsi next.revalidate untuk TTL cache (detik).

fetch("https://...", { next: { revalidate: 3600 } });

Sebagai alternatif, gunakan Opsi Konfigurasi Segmen untuk mevalidasi semua permintaan fetch dalam segmen rute.

layout.js | page.js
export const revalidate = 3600; // melakukan revalidasi setiap jam

Jika kita memiliki beberapa permintaan fetch dalam rute statis dengan frekuensi berbeda, waktu terendah akan dipakai. Untuk rute dinamis, setiap fetch divalidasi ulang secara independen.

Revalidasi Berdasarkan Permintaan

Data dapat divalidasi kembali berdasarkan permintaan melalui jalur (revalidatePath) atau berdasarkan tag cache (revalidateTag) di dalam Pengendali Rute atau Server Action.

Next.js memiliki sistem penandaan cache untuk menghapus permintaan fetch di seluruh rute.

  1. Saat menggunakan fetch, kita memiliki opsi untuk menambahkan entri cache dengan satu atau lebih tag.
  2. Kemudian, kita dapat memanggil revalidateTag untuk memvalidasi ulang semua entri yang terkait dengan tag tersebut.

Sebagai contoh, permintaan fetch berikut menambahkan tag cache koleksi:

app/page.tsx
export default async function Page() {
  const res = await fetch("https://...", { next: { tags: ["koleksi"] } });
  const data = await res.json();
  // ...
}

Kita dapat me-revalidasi ulang pemanggilan fetch yang sudah diberi tag ini dengan cara memanggil revalidateTag didalam server action:

app/actions.ts
"use server";
 
import { revalidateTag } from "next/cache";
 
export default async function action() {
  revalidateTag("collection");
}

Penanganan Kesalahan dan Revalidasi

Jika terjadi kesalahan saat mencoba memvalidasi ulang data, data yang telah berhasil dihasilkan sebelumnya akan terus disajikan dari cache. Pada permintaan selanjutnya, Next.js akan mencoba kembali memvalidasi data.

Menonaktifkan Penyimpanan Data

Permintaan fetch tidak akan disimpan dalam cache jika:

  • Opsi cache: 'no-store' ditambahkan pada permintaan fetch.
  • Opsi revalidate: 0 ditambahkan pada permintaan fetch individu.
  • Permintaan fetch berada dalam Pengendali Router yang menggunakan metode POST.
  • Permintaan fetch dilakukan setelah penggunaan headers atau cookies.
  • Opsi segmen rute const dynamic = 'force-dynamic' digunakan.
  • Opsi segmen rute fetchCache dikonfigurasi untuk melewati cache secara default.
  • Permintaan fetch menggunakan header Authorization atau Cookie dan ada permintaan tanpa cache di atasnya dalam pohon komponen.

Permintaan fetch Individu

Untuk menonaktifkan penyimpanan cache untuk permintaan fetch individu, kita dapat mengatur opsi cache dalam fetch menjadi 'no-store'. Ini akan mengambil data secara dinamis, pada setiap permintaan.

layout.js | page.js
fetch("https://...", { cache: "no-store" });

Permintaan fetch Ganda

Jika kita memiliki beberapa permintaan fetch dalam segmen rute (misalnya, Layout atau Page), kita dapat mengkonfigurasi perilaku penyimpanan cache dari semua permintaan data dalam segmen menggunakan Opsi Konfigurasi Segmen.

Sebagai contoh, dengan menggunakan const dynamic = 'force-dynamic', semua data akan diambil pada saat permintaan, dan segmen akan dirender secara dinamis.

layout.js / page.js
// Tambahkan
export const dynamic = "force-dynamic";

Terdapat daftar panjang opsi Konfigurasi Segmen, memberikan kita kontrol yang sangat halus terhadap perilaku statis dan dinamis dari segmen rute.

Mengambil Data pada Server dengan Pustaka Pihak Ketiga

Dalam kasus di mana kita menggunakan pustaka pihak ketiga yang tidak mendukung atau mengekspos fetch (misalnya, basis data, CMS, atau klien ORM), kita dapat mengkonfigurasi perilaku penyimpanan cache dan revalidasi permintaan tersebut menggunakan Opsi Konfigurasi Segmen Rute dan fungsi cache React.

Apakah data akan disimpan dalam cache atau tidak akan tergantung pada apakah segmen rute tersebut dirender secara statis atau dinamis. Jika segmen tersebut statis (default), hasil permintaan akan disimpan dalam cache dan divalidasi ulang sebagai bagian dari segmen rute. Jika segmen tersebut dinamis, hasil permintaan tidak akan disimpan dalam cache dan akan diambil kembali pada setiap permintaan saat segmen tersebut dirender.

Pada contoh di bawah ini:

  • Opsi revalidate diatur ke 3600, yang berarti data akan disimpan dalam cache dan divalidasi ulang paling lama setiap jam.
  • Fungsi cache React digunakan untuk memoisasi permintaan data.
utils/get-item.ts
import { cache } from "react";
 
export const revalidate = 3600; // revalidate the data at most every hour
 
export const getItem = cache(async (id: string) => {
  const item = await db.item.findUnique({ id });
  return item;
});

Meskipun fungsi getItem dipanggil dua kali, hanya satu query yang akan dilakukan ke basis data.

app/item/[id]/layout.tsx
import { getItem } from "@/utils/get-item";
 
export default async function Layout({
  params: { id },
}: {
  params: { id: string };
}) {
  const item = await getItem(id);
  // ...
}
app/item/[id]/page.tsx
import { getItem } from "@/utils/get-item";
 
export default async function Page({
  params: { id },
}: {
  params: { id: string };
}) {
  const item = await getItem(id);
  // ...
}

Mengambil Data pada Klien dengan Pengendali Rute

Jika kita perlu mengambil data dalam komponen klien, kita dapat memanggil Pengendali Rute dari klien. Pengendali Rute dieksekusi di server dan mengembalikan data ke klien. Ini berguna saat kita tidak ingin mengungkapkan informasi sensitif kepada klien, seperti token API.

Komponen Server dan Pengendali Rute

Karena Komponen Server merender di server, kamu tidak perlu memanggil Pengendali Rute dari Komponen Server untuk mengambil data. Sebaliknya, kamu dapat mengambil data langsung di dalam Komponen Server.

Mengambil Data pada Klien dengan Pustaka Pihak Ketiga

Kamu juga dapat mengambil data pada klien menggunakan pustaka pihak ketiga seperti SWR (opens in a new tab) atau React Query (opens in a new tab). Pustaka-pustaka ini menyediakan API mereka sendiri untuk memoisasi permintaan, penyimpanan cache, revalidasi, dan mutasi data.