Lompat ke konten
Kembali ke modul

Next.js: Fullstack dalam Satu Proyek · 3/9

Mengambil data di server

Component async, bicara langsung ke database, dan tidak pernah mengirim rahasia ke browser.

Baca 28 menit

Setelah pelajaran ini kamu bisa

  • Mengambil data di Server Component async
  • Query database secara langsung, tanpa lapisan API
  • Mengenali dan memperbaiki request waterfall
  • Menjelaskan kenapa pengambilan data sebaiknya di server

Server Component bisa bersifat async dan langsung memakai await. Tanpa useEffect, tanpa state loading, tanpa route API terpisah — datanya sudah ada sebelum HTML-nya dikirim.

tsx
// The old way, in a Client Component: three states and a waterfall.
"use client";
function VenuesOld() {
  const [venues, setVenues] = useState(null);
  const [error, setError] = useState(null);
  useEffect(() => {
    fetch("/api/venues").then((r) => r.json()).then(setVenues).catch(setError);
  }, []);
  if (error) return <p>Failed</p>;
  if (!venues) return <p>Loading...</p>;
  return <List venues={venues} />;
}

// The Server Component way:
async function Venues() {
  const venues = await getVenues();      // straight to the database
  return <List venues={venues} />;
}
Browser-nya tidak pernah membuat request kedua, dan penggunanya tidak pernah melihat spinner untuk data awalnya.

Kamu tidak butuh route API untuk UI-mu sendiri. API ada supaya *client lain* bisa mengakses datamu — aplikasi mobile, integrasi mitra. Halamanmu sendiri sudah berada di server, jadi ia bisa langsung query.

tsx
// This is genuinely what this project does.
// features/progress/progress.ts
import "server-only";
import { query } from "@/features/db";

export function getProgress(userId: number) {
  return query("SELECT lesson_id FROM lesson_progress WHERE user_id = ?", userId);
}

// app/[lang]/dashboard/page.tsx
export default async function DashboardPage() {
  const user = await getSessionUser();
  if (!user) redirect("/en/sign-in");

  const progress = getProgress(user.id);      // direct SQL, no HTTP hop
  return <Progress data={progress} />;
}

Waterfall

Waterfall adalah rangkaian request di mana masing-masing menunggu yang sebelumnya, padahal tidak perlu. Ini kesalahan berurutan-versus-paralel dari modul 3, dan di sebuah server dengan tiga panggilan database, inilah pembeda antara halaman cepat dan halaman lambat.

Coba sendiri

Tiga bentuk pemuatan data, diukur waktunya. Yang tengah adalah jebakannya.

Hasil

Tekan Jalankan untuk melihat hasilnya.

Ini jalan di browser kamu, di dalam sandbox. Apa pun yang kamu tulis di sini tidak bisa merusak situs.

Tugas praktik

Di proyek ini, buka app/[lang]/dashboard/page.tsx dan daftar setiap pemanggilan data yang dilakukannya. Apakah ada yang cukup independen untuk dijalankan dengan Promise.all? Lalu buka features/progress/progress.ts dan pastikan setiap string SQL memakai placeholder ? alih-alih interpolasi string — dan jelaskan apa yang akan rusak kalau ada satu yang tidak.

Hasil yang diharapkan

Semua query berparameter; pemanggilan di dashboard-nya sebagian besar bergantung pada session.