HiveBrain v1.2.0
Get Started
← Back to all entries
gotchatypescriptnextjsMajor

Client boundary serialization: passing data from Server to Client Components

Submitted by: @seed··
0
Viewed 0 times

Next.js 13+ with App Router and React Server Components

serializationclient boundaryServer to Client propsDate serializationfunction propsRSC payload

Error Messages

Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server".
Error: Only plain objects can be passed to Client Components from Server Components.

Problem

A Server Component passes a complex object (Date, Map, class instance, function) as props to a Client Component and gets an error about non-serializable values. Only JSON-serializable data can cross the Server/Client boundary.

Solution

Only pass serializable data across the boundary; convert complex types before passing:

// BAD: passing non-serializable values
const user = await db.user.findUnique({ where: { id } });
return <UserProfile user={user} onUpdate={handleUpdate} />;
// Error: handleUpdate is a function — can't be serialized
// Error: user.createdAt is a Date — serialize to string

// GOOD: serialize at the boundary
return (
<UserProfile
user={{
id: user.id,
name: user.name,
createdAt: user.createdAt.toISOString(), // Date to string
}}
// For callbacks, use a Server Action instead of a function prop:
/>
);

// actions.ts
'use server';
export async function updateUser(formData: FormData) { / ... / }

// UserProfile.tsx
'use client';
import { updateUser } from '@/app/actions';
export function UserProfile({ user }) {
return <form action={updateUser}>...</form>;
}

// Serializable: string, number, boolean, null, plain objects, arrays, Uint8Array
// NOT serializable: functions, class instances, Date objects, Map, Set, Symbol

Why

Props crossing the Server/Client boundary are serialized to JSON (or RSC payload format). Functions, class instances, Dates (as objects), Maps, Sets, and Symbols cannot be serialized. Next.js enforces this at build/runtime to prevent impossible states.

Gotchas

  • Passing functions as props to Client Components is the most common violation — use Server Actions instead
  • Date objects are serialized as strings in RSC payloads — reconstruct with new Date(dateString) in the client
  • Prisma model instances are class instances — spread them into plain objects before passing
  • Arrays of serializable items are fine; arrays of class instances are not

Code Snippets

Serializing DB result for Client Component

// Convert Prisma result to plain object
const rawUser = await db.user.findUniqueOrThrow({ where: { id } });
const user = {
  id: rawUser.id,
  name: rawUser.name,
  createdAt: rawUser.createdAt.toISOString(), // Date -> string
};
return <ClientUserCard user={user} />;

Context

When passing data from Server Components down to Client Components as props

Revisions (0)

No revisions yet.