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.
// 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} />;
}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.
// 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.
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.