React Server Components memperkenalkan batas baru yang memisahkan kode yang dijalankan di server dari yang dijalankan di klien. Batas ini bukan sekadar pembagi logika, melainkan sebuah proses serialisasi yang memeriksa setiap prop yang diteruskan ke komponen klien. React berjalan melalui setiap nilai, mencari cabang serialisasi yang sesuai, dan langsung berhenti ketika menemukan sesuatu yang tidak dikenal—seringkali menyebabkan kegagalan build yang misterius di tahap prerender.
Proses serialisasi ini, yang diimplementasikan dalam Flight (bagian dari React 19), bekerja seperti pemeriksaan keamanan bertingkat. Setiap prop diperiksa berdasarkan jenisnya: primitive, Date, objek biasa, referensi klien, atau referensi server. Jika sebuah nilai tidak memiliki cabang dalam serializer, pengecekan prototipe akan menolak instance dengan prototipe selain Object.prototype, termasuk class instance dan objek yang dibuat dengan null prototype. Contoh seperti `new RegExp()`, `new WeakMap()`, atau `new Error()` menunjukkan perilaku yang tidak intuitif—beberapa berhasil, sementara yang lain melempar error yang tidak langsung terlihat.
Empat pola umum yang sering menyebabkan masalah adalah prop `Error`, instance class yang menyerupai POJO, objek `{ onSelect: fn }` yang terlihat seperti konfigurasi, dan fungsi yang tidak dapat diidentifikasi oleh React. `new Error('boom')` sebenarnya berhasil menyeberang, tetapi di produksi branch-nya dikosongkan, sehingga pesan error hilang dan membingungkan pengembang. Instance class yang tidak memiliki properti tambahan selain data tetap ditolak karena pemeriksaan prototipe, meskipun terlihat seperti objek biasa. Wrapper `{ onSelect: fn }` terlihat seperti objek konfigurasi, tetapi React turun ke properti anak dan menemukan fungsi, memicu error “event handlers cannot be passed…”.
Dua perangkap tersembunyi adalah: pertama, objek konfigurasi yang terlihat aman (`options={{ ... }}`) sebenarnya adalah fungsi prop dengan pembungkus tambahan, dan kedua, keyakinan bahwa bug hanya berasal dari kebocoran server-only. Checker di versi 0.2.0 mulai gagal pada impor server-only, tetapi aturan ini terlalu luas dan mengecap proyek yang menggunakan alias `./lib/shim` sebagai kebocoran, meskipun tidak berbahaya. Kesalahpahaman ini menunjukkan bahwa apa yang dianggap sebagai bug mahal seringkali adalah konsekuensi dari serialisasi, bukan kebocoran nyata.
Bagi pengembang di Indonesia, memahami batasan ini sangat penting karena ekosistem JavaScript terus berkembang, terutama dengan adopsi server-first frameworks seperti Next.js dan Remix. Kesalahan dalam penanganan prop tidak hanya menyebabkan kegagalan build tetapi juga meningkatkan waktu debugging, yang berdampak pada produktivitas dan kualitas rilis. Memahami serializer Flight membantu tim menulis kode yang lebih robust dan menghindari kegagalan CI yang tidak perlu.
Praktik terbaik saat ini mencakup pemeriksaan statis terhadap prop yang akan diteruskan ke komponen klien, menggunakan tipe TypeScript untuk membatasi nilai, dan menguji secara manual kasus-kasus edge seperti instance class, simbol global, dan objek dari realm lain. Menulis tes yang mengeksplorasi batas serialisasi—seperti prop `Date`, `Set`, `Map`, dan referensi klien—dapat menangkap masalah sebelum masuk ke produksi.
Di masa depan, React mungkin akan memperluas serializer untuk mencakup lebih banyak tipe data, tetapi saat ini pengembang harus berhati-hati. Komunitas pengembang Indonesia harus terus mengikuti perkembangan terbaru di React 19 dan Flight, karena optimasi server component akan menjadi semakin penting dalam aplikasi web yang semakin kaya fitur. Menguasai batasan ini bukan hanya tentang menghindari error build, tetapi juga tentang memanfaatkan sepenuhnya performa dan keamanan yang ditawarkan oleh rendering di server.
Di era di mana aplikasi web bersaing untuk kecepatan dan efisiensi, memahami apa yang sebenarnya dapat menyeberangi batas komponen server adalah keahlian penting yang akan membedakan aplikasi yang handal dari yang bermasalah.