Props Serializable dan Batas Aman untuk Cara Passing Data Server Component ke Client Component

Cara passing data Server Component ke Client Component yang benar adalah fetch di Server Component, lalu kirim hasilnya lewat props ke komponen bertanda use client. Langkah yang sering terlewat adalah memastikan data itu serializable sebelum dikirim. Objek polos, string, number, boolean, array, dan null aman. Class instance, function, Map, Set, dan simbol tidak ikut terkirim dengan benar.

Kirim Data dari Server ke Client lewat Props

Pola ini menjaga secret tetap di server. Token database, API key, dan cookie httpOnly tidak boleh ikut ke props. Kirim hanya data yang memang perlu dirender atau dipakai interaksi di browser.

// app/dashboard/page.tsx
import StatsClient from "./stats-client";

async function getStats() {
  const res = await fetch(process.env.STATS_API_URL as string);
  if (!res.ok) throw new Error("Gagal memuat statistik");
  return res.json();
}

export default async function DashboardPage() {
  const stats = await getStats();
  const payload = {
    total: Number(stats.total ?? 0),
    updatedAt: new Date(stats.updatedAt).toISOString(),
  };
  return <StatsClient initialStats={payload} />;
}
// app/dashboard/stats-client.tsx
"use client";

export default function StatsClient({ initialStats }) {
  return <p>Total: {initialStats.total}</p>;
}
  1. Buat Server Component sebagai wrapper halaman atau layout.
  2. Lakukan fetch dan validasi bentuk data di server.
  3. Ubah nilai non-serializable menjadi string atau number.
  4. Kirim data bersih itu sebagai props ke Client Component.
  5. Pakai props di client untuk state awal, event, atau efek browser.

Batasan Props dan Pola yang Aman Dipakai

Props melewati boundary serialisasi React. Data yang tidak bisa diubah ke JSON akan hilang, berubah bentuk, atau memicu error build dan runtime.

  • Boleh dikirim: objek polos, array, string, number, boolean, null.
  • Ubah dulu: Date menjadi string ISO, BigInt menjadi string, undefined menjadi null.
  • Jangan kirim: function, class instance, Map, Set, WeakMap, simbol, stream.
  • Jangan kirim secret: password, token mentah, API secret, connection string.
  • Untuk data besar, kirim ringkasan atau halaman aktif saja, bukan seluruh tabel.
Jenis Data Status di Props Penanganan
Objek dan array polos Aman Kirim langsung setelah validasi
Date Tidak stabil Ubah ke toISOString lalu parse di client
Function atau class Ditolak Pindah logika ke Server Action atau client

Saat Client Component butuh banyak bagian server, pakai komposisi children. Server Component merender konten statis sebagai children, lalu Client Component hanya membungkus interaksinya. Pola ini mengurangi prop drilling dan menjaga bundle client tetap kecil.

// app/report/page.tsx
import FilterClient from "./filter-client";
import ReportTable from "./report-table";

export default function ReportPage() {
  return (
    <FilterClient>
      <ReportTable />
    </FilterClient>
  );
}

FAQ

Apakah function bisa dikirim sebagai props?

Tidak. Function bukan data serializable, jadi pindahkan eksekusinya ke Server Action atau definisikan ulang handler di Client Component.

Kenapa data Date error saat passing?

Date diserialisasi menjadi string, sehingga method seperti getTime hilang. Kirim ISO string lalu buat ulang dengan new Date di client.

Kapan fetch dipindah ke Client Component?

Pindah saat data tergantung interaksi browser, input pengguna yang berubah cepat, atau API yang hanya bisa diakses dari client.